29

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

2 Where検索を実行できますが、実行時間は2 * Nです(これはO(n)のままですが、2倍の時間がかかり、明らかに好ましくありません)

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

自分で単一の線形パスを実行することもできますが(ここでは拡張メソッドにリファクタリングされます)、これはこのコード全体をドラッグする必要があることを意味し、カスタムコードが増えると保守性が低下します。

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つの線形パスに分割するためのネイティブサポートがありますか?

4

4 に答える 4

29

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

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

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

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

これは、数値が奇数か偶数かに基づいて2つの「グループ」に分割されます。

于 2012-08-13T17:02:04.017 に答える
11

リードコプシーの答えは言及していますToLookup、そしてそれは魅力的なようです。

var lookup = nums.ToLookup(IsEven);

ここIsEvenで、は期待されるシグニチャとリターンタイプを持つ静的メソッドです。それで

IEnumerable<int> even = lookup[true];
IEnumerable<int> odd = lookup[false];
于 2012-08-13T18:16:27.840 に答える
5

ロジックが排他的である場合、あなたの場合、あなたは次のようにすることができます

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
}
于 2012-08-13T17:04:20.460 に答える
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;
   }
 }

小さなコンパイラエラーについてお詫びします。これは頭のてっぺんから行いました。偶数/奇数の代わりに、述語を追加できます。

于 2013-07-17T15:03:24.013 に答える