2012-06-06 1 views
8

A HashSet<T>は、O(1)に特定の項目が含まれているかどうかを判断できます。私は私のカスタムクラスのEquals()GetHashCode()をオーバーライドする場合、私は、オブジェクトAを持つことができ、ある別のオブジェクトA」ではないアイデンティティによって等しいがためEquals()戻りtrueGetHashCode()は、同じハッシュコードを返します。O(1)内のHashSet <T>から等しいオブジェクトを取得します。

ここで、Aがハッシュセットにあるとすれば、A '(ハッシュセットの観点からはAに等しい)で与えられたO(1)のAを検索したいと考えています。

var a = new MyClass("A"); 
var a_prime = new MyClass("A"); 
Debug.Assert(a.Equals(a_prime)); 
Debug.Assert(a.GetHashCode() == a_prime.GetHashCode()); 

var set = new HashSet<MyClass>(); 
set.Add(a); 
Debug.Assert(set.Contains(a_prime)); 

// This:  
var retrieved_a = set.Get(a_prime); 

どのようにするには?

thisは私が探している答えをしていない、とthisは全く答えを持っていないことに注意してください。)


いくつかの背景情報に:私はインターン自分へのセットを使用したいですオブジェクトはC#のinterns文字列と同じ方法です。等しいオブジェクトは1つのインスタンスしか必要ありません。このようにして、私はそのようなオブジェクトにメタデータを追加し、そのメタデータなしで他の同等のインスタンスが存在しないことを確認できます。

+6

「A」から「A」までの辞書マッピングを使用するだけではどうですか? –

+0

[HashSetから実際のアイテムを取り出す方法?](http://stackoverflow.com/questions/7760364/how-to-retrieve-actual-item-from-hashsett) – nawfal

+0

もう1つの[アクセス方法参照なしハッシュ値の列挙なし?](http://stackoverflow.com/questions/7290443/how-to-access-the-reference-values-of-a-hashsettvalue-without -enumeration?) – nawfal

答えて

7

HashSetには方法がありません。

代わりDictionaryを使用することができます。

var dict = new Dictionary<MyClass, MyClass>(); 
dict[a] = a; 
Debug.Assert(dict.ContainsKey(a_prime)); 
var retrieved_a = dict[a_prime]; 
+0

私は常に自分自身にマップする辞書を作るのをやめました。これは悪い習慣ですか?それとも、私は何も心配していませんか? –

+0

@ハンスいつものように、それは異なります。なぜそれが悪い習慣だと思いますか?なぜあなたはそれらを避けますか? – svick

+3

@svick私は知らない、それはちょうど私には不思議そうだ。私はそれを避けるための具体的な理由はないと思うが、私は決してそのような構造を使う必要はなかったが、何らかの理由で 'dict [a] = a;を見ると' –

1

私が正しくリコールHashSetがありながら、Dictionaryは、基本的な集合演算の時定数の実装を持っていません。これは、HashSetから他の複雑さを増やすことなく、一定時間の等間隔ルックアップで実装する方法です。多くのランダム要素を取得する必要がある場合は、このアプローチを使用することが重要です。私がC#を知らないので、私が下に書くのはJavaシンタックスですが、そのアイデアは言語に依存しません。

class MySet<A> { 
    ArrayList<A> contents = new ArrayList(); 
    HashMap<A,Integer> indices = new HashMap<A,Integer>(); 

    //selects equal element in constant time 
    A equalElement(A input) { 
     return contents.get(indices.get(input)); 
    } 

    //adds new element in constant time 
    void add(A a) { 
     indices.put(a,contents.size()); 
     contents.add(a); 
    } 

    //removes element in constant time 
    void remove(A a) { 
     int index = indices.get(a); 
     contents.set(index,contents.get(contents.size()-1)); 
     contents.remove(contents.size()-1); 
     indices.set(contents.get(contents.size()-1),index); 
     indices.remove(a); 
    } 

    //all other operations (contains(), ...) are those from indices.keySet() 
} 
+0

申し訳ありません、ランダムはタイプミスでした。私は今方法を修正しました。 基本的には、HashSetを使用する代わりに、HashMap *と* ArrayListを使用します.HashMapとArrayListは、同じ要素と、ArrayList内のその要素のインデックスを指すHashMapを含みます。 HashSetからのシンプルな "はい、私はすでにこのキーを持っています"の代わりに、 "はい、私はすでにこのキーを持っていて、それは整数" i "を指しています。次に、ArrayListでオブジェクトを 'i'の位置に置くことでオブジェクトを取得できます。 – user1111929

+0

訂正ありがとう!今それははるかに関連性が高いです!副次的なこととして、私はその "一定の時間"の主張について非常に注意を払っています。私はHashMapsが最悪の場合O(1)フェッチ時間を保証しているとは思わない、それは平均O(1)だと思うし、例えばキーのGetHashCodeで邪魔になるならば、地図のとにかく、-1と前のコメントが削除されました。 – quetzalcoatl

+0

あなたは正しいです。「一定の時間」は「平均時間:定数」を意味します。 – user1111929

関連する問題