2012-08-13 6 views
25

アイテムのコレクションがある場合、コレクションを述語に基づいて2つのサブコレクションに分割するにはどうすればよいですか?LINQはネイティブでコレクションを2つに分割することをサポートしていますか?

あなたは2件の検索を行うことができますが、その後の実行時間は2 *

IEnumerable<int> even = nums.Where(i => IsEven(i)); 
IEnumerable<int> odd = nums.Where(i => !IsEven(i)); 

あなたが行うことができます(まだO(n)は、二倍の時間がかかるとは明らかに有利ではありませんが、)N (ここでは拡張メソッドにリファクタリングしています)、これはあなたがこのコードを全部ドラッグしなければならないことを意味し、より多くのカスタムコードは物事を保守しにくくします。

public static void SplitOnPred<T>(
     this IEnumerable<T> collection, 
     Func<T, bool> pred, 
     out IEnumerable<T> trueSet, 
     out IEnumerable<T> falseSet 
    ) { 
     List<T> trueSetList = new List<T>(); 
     List<T> falseSetList = new List<T>(); 
     foreach(T item in collection) { 
      if(pred(item)) { 
       trueSetList.Add(item); 
      } else { 
       falseSetList.Add(item); 
      } 
     } 
     trueSet = trueSetList; 
     falseSet = falseSetList; 
} 

質問: LINQは1つのリニアパスでコレクションを分割するための任意のネイティブサポートを持っていますか?

+0

なぜ1つの線形パスが必要ですか? –

+3

@SaeedAmiriその必要条件ではなく、2回のリニアパスが_good_十分です_ほとんどの場合、私は決して満足できるパフォーマンスではありません:P – James

答えて

25

LINQには1回の線形パスでコレクションを分割するためのネイティブサポートがありますか?

コレクションを述語に基づいて2つのバージョンに分割する組み込みメソッドはありません。投稿したのと同様の独自の方法を使用する必要があります。

最も近い組み込みメソッドはGroupBy(またはToLookup)です。あなたは、奇数または偶数でグループができます

var groups = nums.GroupBy(i => IsEven(i)); 

これは数字が奇数か偶数であるかどうかに基づいて、2つの「グループ」に分かれます。

5

まあロジックがあなたのケースには、esclusiveであれば、あなたは

var list = new List<int> {1,2,3,4,5,6,7,8,9,10};  
var result = list.GroupBy(x=> x%2==0); 

のように行うことができますし、result

foreach(var r in result) 
{ 
    if(r.Key) 
    //EVEN 
    else 
    //ODD 
} 
8

リードCopseyの答えはToLookupに言及し、それが魅力的と思われます。

var lookup = nums.ToLookup(IsEven); 

IsEvenは、期待される署名と戻り値の型を持つ静的メソッドです。その後

IEnumerable<int> even = lookup[true]; 
IEnumerable<int> odd = lookup[false]; 
1

あなたは遅延実行をサポートしたい、このように機能や拡張機能を使用する場合は、次のいずれかの小さなコンパイラエラーのため

IEnumerable<T> Split<T>(this IEnumerable<T> source, out IEnumerable<T> odd) 
{ 
    IList<T> oddCollector = new List<T>(); 
    Bool odd = true; 
    foreach(T item in source) 
    { 
     if(odd) 
     { 
      oddCollector.Add(item); 
     } 
     else 
     { 
      yield return item; 
     } 
     odd = !odd; 
    } 
} 

私の謝罪、私は私の頭の上からこれをしました。偶数/奇数の代わりに、述語を追加することができます。

+0

警告これは最初に読み込んだり、列挙型は交互に並んでいます。あなたが最初に奇妙なことを読んだら、あなたはすべての結果を得ることはできません。 – csauve

関連する問題