0

3つの列を含む汎用リスト(またはIQueryable)を検索しています。1と2に基づいて3列の値を見つけようとしていますが、検索が非常に遅くなります。単一の検索の場合、速度は目立ちませんが、この検索をループで実行しています。700回の反復では、合計で2分以上かかるため、使用できません。列1と2はintであり、列3はdoubleです。これが私が使用しているlinqです:

public static Distance FindByStartAndEnd(int start, int end, IQueryable<Distance> distanceList)
{
    Distance item = distanceList.Where(h => h.Start == start && h.End == end).FirstOrDefault();
    return item ;
}

IQueryableリストには最大60,000のエントリが存在する可能性があります。それはかなり多いことは知っていますが、検索に問題が生じるとは思いませんでした。

だから私の質問は、3分の1の値を取得するために2つの列を一致させる必要があるときにコレクションを検索するためのより良い方法はありますか?700回の検索すべてをほぼ瞬時に行う必要があると思いますが、それぞれに約300ミリ秒かかり、すぐに増加します。

更新-最終解決策#######################

Tupleこれで、 withstartとキーをキーとして使用して辞書を作成しましたend。これが正しい解決策になると思います。

var dictionary = new Dictionary<Tuple<int, int>, double>();

var key = new Tuple<int, int>(Convert.ToInt32(reader[0]), Convert.ToInt32(reader[1]));
var value = Convert.ToDouble(reader[2]);

if (value <= distance)
{
    dictionary.Add(key, value);
}
var key = new Tuple<int, int>(5, 20);

正常に動作します-はるかに高速です

4

5 に答える 5

5

列1と2がキーを作成する辞書を作成します。辞書を一度作成すると、検索はほぼ瞬時に行われます。

于 2012-10-24T09:06:56.643 に答える
0

コレクションクラスとモデルクラスを制御できる場合は、クラスのプロパティにインデックスを付けることができるライブラリがあり、検索を大幅に高速化できます。

http://i4o.codeplex.com/

于 2012-10-24T09:07:25.223 に答える
0

問題は、アイテムを返すたびにLINQが式ツリーを実行する必要があることです。複数の開始値と終了値を使用してこのメ​​ソッドを呼び出すだけです

public static IEnumerable<Distance> FindByStartAndEnd
    (IEnumerable<KeyValuePair<int, int>> startAndEnd,
    IQueryable<Distance> distanceList)
{

    return
        from item in distanceList
        where 
            startAndEnd.Select(s => s.Key).Contains(item.Start)
            && startAndEnd.Select(s => s.Value).Contains(item.End)
        select item;
}
于 2012-10-24T09:09:16.727 に答える
0

hashSetを試してみます。これは物事をスピードアップするはずです;)

于 2012-10-24T09:11:09.527 に答える
0

たとえば、最初の2つの列を連結して単一の値を作成し、それをlong辞書のキーとして使用します。

public long Combine(int start, int end) {
  return ((long)start << 32) | end;
}

Dictionary<long, Distance> lookup = distanceList.ToDictionary(h => Combine(h.Start, h.End));

次に、値を検索できます。

public static Distance FindByStartAndEnd(int start, int end, IQueryable<Distance> distanceList) {
  Distance item;
  if (!lookup.TryGetValue(Combine(start, end), out item) {
    item = null;
  }
  return item;
}

辞書からアイテムを取得することは、O(1)操作に近いため、O(n)操作とは劇的な違いがあり、アイテムをループしてアイテムを見つけることができます。

于 2012-10-24T09:14:07.587 に答える