6

があり、値型であるとの 2 つの変数の組み合わせを検索してList<Thing> things、多数の を頻繁に取得する必要があります。私が今やっていることは単純です。しかし、私は非常に多くの検索を頻繁に行っているため、より効果的な方法が必要です。ThingT1 f1T2 f2things.Where(t => t.Field1 == f1 && t.Field2 == f2)

幸いなことに、things要素を削除または追加する必要はありません。そのため、作成時にリストを解析してDictionary<T1, Lookup<T2, Thing>>. ただし、特に解析が追加されているため、これは面倒です。さらに多くのフィールドを検索する必要がある場合は、非常に面倒です。3 つのフィールドは のようになりますDictionary<T1, Dictionary<T2, Lookup<T3, Thing>>>

次に考えたのは、 を作ることでしたLookup<Tuple<T1,T2,T3,...>,Thing>。ただし、この場合、Tuple は参照型であるため、キーが実際に機能するかどうかはわかりません。

. _ Lookup<ValueType<T1,T2,T3,...>,Thing> things_things[new ValueType<T1,T2,T3,...>(f1, f2, f3, ...)]

ハッシュテーブルのパフォーマンス上の利点を維持し、単に次のようなものを入力できる、よりエレガントなソリューションはありIEnumerable<Thing> found = things[f1, f2, f3, ...];ますか?

4

5 に答える 5

3

Lookup<Tuple<T1,T2,T3,...>,Thing>とをTupleオーバーライドするため、機能します。EqualsGetHashCode

ルックアップ構文の見苦しさを軽減するために、Tuple.Create型推論をサポートするwhichを使用できます。コードはになりthings[Tuple.Create(f1, f2, f3, ...)]ます。それでも醜い場合は、個々の値をパラメーターとして受け取るヘルパーメソッドを追加するのは簡単です。

また、キーに対して独自の不変のクラス(または値型)を作成することも検討します。これにより、の代わりにクリーンなフィールド名を取得できますItemX。あなたはただオーバーライドEqualsGetHashCodeて一貫してする必要があります。

于 2012-08-24T17:11:18.547 に答える
2

複数のルックアップを作成し、それらを交差させて検索を行うことができます。これはやや単純化された例ですが、アイデアを説明する必要があります。

class Test {
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

var list = new List<Test> {
    new Test {A = "quick", B = "brown", C = "fox"}
,   new Test {A = "jumps", B = "over", C = "the"}
,   new Test {A = "lazy", B = "dog", C = "quick"}
,   new Test {A = "brown", B = "fox", C = "jumps"}
,   new Test {A = "over", B = "the", C = "lazy"}
,   new Test {A = "dog", B = "quick", C = "brown"}
,   new Test {A = "fox", B = "jumps", C = "over"}
,   new Test {A = "the", B = "lazy", C = "dog"}
,   new Test {A = "fox", B = "brown", C = "quick"}
,   new Test {A = "the", B = "over", C = "jumps"}
,   new Test {A = "quick", B = "dog", C = "lazy"}
,   new Test {A = "jums", B = "fox", C = "brown"}
,   new Test {A = "lazy", B = "the", C = "over"}
,   new Test {A = "brown", B = "quick", C = "dog"}
,   new Test {A = "over", B = "jumps", C = "fox"}
,   new Test {A = "dog", B = "lazy", C = "the"}
};
var byA = list.ToLookup(v => v.A);
var byB = list.ToLookup(v => v.B);
var byC = list.ToLookup(v => v.C);
var all = byA["quick"].Intersect(byB["dog"]);
foreach (var test in all) {
    Console.WriteLine("{0} {1} {2}", test.A, test.B, test.C);
}
all = byA["fox"].Intersect(byC["over"]);
foreach (var test in all) {
    Console.WriteLine("{0} {1} {2}", test.A, test.B, test.C);
}

このプリント

quick dog lazy
fox jumps over
于 2012-08-24T17:09:03.070 に答える
1

ある種のフィールドの組み合わせをキーとしてハッシュ テーブルを使用することを検討しましたか? これが実行可能かどうかを判断するには、あなたのデータセットについて十分に知りません。キーは一意である必要があるためです。ただし、メモリ内のルックアップにハッシュテーブルを使用して追加または削除を行っていないため、取得できる速度はほぼ同じです。

于 2012-08-24T17:03:10.317 に答える
1

私があなたを正しければ、以下の例で使用できHashtableますTuple

        // populate Hastable
        var hash = new Hashtable();            
        var tuple = Tuple.Create("string", 1, 1.0);
        hash.Add(tuple,tuple);

        // search for item you want
        var anotherTuple = Tuple.Create("string", 1, 1.0);
        // result will be tuple declared above
        var result = hash[anotherTuple];

より複雑な解決策 (重複キーが必要な場合):

public class Thing
{
    public int Value1 { get; set; }

    public double Value2 { get; set; }

    public string Value3 { get; set; }

    // preferable to create own Equals and GetHashCode methods
    public Tuple<int, double>  GetKey()
    {
       // create key on fields you want 
       return Tuple.Create(Value1, Value2);
    }
}

利用方法

 var t1 = new Thing() {Value1 = 1, Value2 = 1.0, Value3 = "something"};
 var t2 = new Thing() {Value1 = 1, Value2 = 2.0, Value3 = "something"};
 var hash = new [] { t1, t2 }.ToLookup(item => item.GetKey());

 var criteria = new Thing() { Value1 = 1, Value2 = 2.0, value3 = "bla-bla-bla" };
 var r = hash[criteria.GetKey()]; // will give you t1
于 2012-08-24T17:03:22.733 に答える
0

Linq Where または Dictionary of Dictionaries は、おそらく最も美しいものです。しかし、データをどのように整理しているかという問題の方が重要かもしれません。

EG これは、人のデータにアクセスするためのきれいな方法ではありません。

people["FirstName"]["LastName"] 

通常はそのほうがよいので、より単純なキーを考えてみてください。

于 2012-08-24T17:12:40.663 に答える