3

そのため、処理して 1 つのリストにマージしようとしているいくつかの異なるリストがあります。

以下は、より良い方法があるかどうかを確認したいコードのスニペットです。私が尋ねている理由は、これらのリストのいくつかはかなり大きいからです。これを行うより効率的な方法があるかどうかを確認したいと思います。

ご覧のとおり、リストをループ処理しています。最初に、CompanyId がリストに存在するかどうかを確認します。そうであれば、処理しようとしているリスト内の項目を見つけます。

pList は私の処理リストです。さまざまなリストの値をこのリストに追加しています。

Exist と Find を達成するための「より良い方法」があるかどうか疑問に思っています。

    boolean tstFind = false;
    foreach (parseAC item in pACList)
    {
        tstFind = pList.Exists(x => (x.CompanyId == item.key.ToString()));

        if (tstFind == true)
        {
            pItem = pList.Find(x => (x.CompanyId == item.key.ToString()));
            //Processing done here.  pItem gets updated here
            ...
         }

補足として、結合を使用してそれがより高速かどうかを確認する方法を調査します。しかし、私はまだそこにたどり着いていません。上記のコードは、この問題を解決するための最初のカットであり、うまくいくようです。しかし、時間があるので、まだ良い方法がないか見てみたいと思います。

どんな入力でも大歓迎です。

時間の調査結果:

  • 私の現在の Find and Exists コードは、pACList 内の 550 万項目をループするのに約84 分かかります。

  • pList.firstOrDefault(x=> x.CompanyId == item.key.ToString()); の使用 pACList の 550 万項目をループするのに54 分かかります

4

6 に答える 6

3

FirstOrDefaultアイテムを2回検索する代わりに、を使用してアイテムを取得できます(1回目はアイテムが存在するかどうかを定義し、2回目は既存のアイテムを取得します)。

var tstFind = pList.FirstOrDefault(x => x.CompanyId == item.key.ToString());

if (tstFind != null)
{            
   //Processing done here.  pItem gets updated here        
}
于 2013-01-28T20:10:37.407 に答える
3

はい、ハッシュテーブルを使用して、アルゴリズムが現在の O(n*m) ではなく O(n) になるようにします。

var pListByCompanyId = pList.ToDictionary(x => x.CompanyId);
 foreach (parseAC item in pACList)
    {
        if (pListByCompanyId.ContainsKey(item.key.ToString()))
        {
            pItem = pListByCompanyId[item.key.ToString()];
            //Processing done here.  pItem gets updated here
            ...
         }
于 2013-01-28T20:13:56.263 に答える
2

linqを使用して、フィルター処理されたリストを反復処理できます

foreach (parseAC item in pACList.Where(i=>pList.Any(x => (x.CompanyId == i.key.ToString()))))
    {
            pItem = pList.Find(x => (x.CompanyId == item.key.ToString()));
            //Processing done here.  pItem gets updated here
            ...
    }
于 2013-01-28T20:11:06.187 に答える
2

このタイプの操作にリストを使用すると、O(MxN) になります (M は pACList のカウント、N は pList のカウントです)。さらに、pACList を 2 回検索しています。この問題を回避するにpList.FirstOrDefaultは、@lazyberezovsky の推奨に従って使用してください。

ただし、可能であれば、リストの使用は避けたいと思います。検索しているDictionaryキーでインデックスを作成すると、検索時間が大幅に短縮されます。

于 2013-01-28T20:12:56.730 に答える
2

別のリスト内の各項目に対してリストで線形検索を行うことは、大規模なデータ セットでは効率的ではありません。より効率的に検索できるテーブルまたはディクショナリにキーを配置して、2 つのテーブルを結合できるようにすることをお勧めします。これを自分でコーディングする必要さえありません。必要なのはJoin操作です。それぞれが同じキーにマップする各シーケンスから、アイテムのすべてのペアを取得する必要があります。

以下のメソッドの実装を引き出すか、適切な型に変更Fooしてメソッドとして使用します。Bar

public static IEnumerable<Tuple<Bar, Foo>> Merge(IEnumerable<Bar> pACList
    , IEnumerable<Foo> pList)
{
    return pACList.Join(pList, item => item.Key.ToString()
        , item => item.CompanyID.ToString()
            , (a, b) => Tuple.Create(a, b));
}

同じキーを持つため、この呼び出しの結果を使用して 2 つのアイテムをマージできます。

内部的には、メソッドは実際に検索を行う前に効率的な検索を可能にするルックアップ テーブルを作成します。

于 2013-01-28T20:36:17.130 に答える
1
  1. pList を HashSet に変換してから、pHashSet.Contains() をクエリします。複雑さ O(N) + O(n)

  2. CompanyId で pList をソートし、Array.BinarySearch() = O(N Log N) + O(n * Log N ) を実行します。

  3. Max company id が極端に大きくない場合は、i 番目の位置に会社 ID i を持つアイテムが存在する場所にそれらを作成して配列します。これ以上速いものはありません。

ここで、N は pList のサイズ、n は pACList のサイズです。

于 2013-01-28T20:15:51.153 に答える