任意の数のコレクションがあり、それぞれに同じタイプのオブジェクトが含まれているとします(たとえば、List<int> foo
およびList<int> bar
)。これらのコレクション自体がコレクションに含まれていた場合(例:タイプList<List<int>>
、SelectMany
を使用して、それらをすべて1つのコレクションに結合できます。
ただし、これらのコレクションがまだ同じコレクションにない場合は、次のようなメソッドを作成する必要があると思います。
public static IEnumerable<T> Combine<T>(params ICollection<T>[] toCombine)
{
return toCombine.SelectMany(x => x);
}
それを次のように呼び出します:
var combined = Combine(foo, bar);
上記のCombine
のようなユーティリティメソッドを記述することなく、(任意の数の)コレクションを結合するためのクリーンでエレガントな方法はありますか? LINQでそれを行う方法があるはずですが、おそらくそうではないはずです。
LINQの .Concat()
?をお探しかもしれません。
_var combined = foo.Concat(bar).Concat(foobar).Concat(...);
_
または、.Union()
は重複する要素を削除します。
連結する複数の大きなシーケンスがある場合、拡張メソッドとしてのConcat
は私のコードではあまりエレガントではありません。これは単にコードのインデント/フォーマットの問題であり、非常に個人的なものです。
確かに次のように見えます:
var list = list1.Concat(list2).Concat(list3);
次のように読めば、それほど読みにくい
var list = list1.Select(x = > x)
.Concat(list2.Where(x => true)
.Concat(list3.OrderBy(x => x));
または、次のような場合:
return Normalize(list1, a, b)
.Concat(Normalize(list2, b, c))
.Concat(Normalize(list3, c, d));
またはあなたの好みのフォーマットは何でも。複雑な連結により事態は悪化します。上記のスタイルと私のsortの認知的不協和の理由は、最初のシーケンスがConcat
メソッドの外側にあるのに対し、後続のシーケンスは中にあります。私はむしろ、拡張スタイルではなく、静的なConcat
メソッドを直接呼び出すことを好みます。
var list = Enumerable.Concat(list1.Select(x => x),
list2.Where(x => true));
シーケンスのより多くの連結については、OPと同じ静的メソッドを使用します。
public static IEnumerable<T> Concat<T>(params IEnumerable<T>[] sequences)
{
return sequences.SelectMany(x => x);
}
だから私は書くことができます:
return EnumerableEx.Concat
(
list1.Select(x = > x),
list2.Where(x => true),
list3.OrderBy(x => x)
);
良く見えます。私が記述しなければならない余分な、そうでなければ冗長なクラス名は、私のシーケンスがConcat
呼び出しでよりきれいに見えることを考えると、私にとって問題ではありません。 C#6で問題は少なくなりました。あなたはただ書くことができます:
return Concat(list1.Select(x = > x),
list2.Where(x => true),
list3.OrderBy(x => x));
C#には次のようなリスト連結演算子が必要でした。
list1 @ list2 // F#
list1 ++ list2 // Scala
そのようにはるかにクリーナー。
doコレクションのコレクションがある場合、つまりList<List<T>>
、Enumerable.Aggregate
は、すべてのリストを1つにまとめるよりエレガントな方法です。
var combined = lists.Aggregate((acc, list) => { return acc.Concat(list); });
つかいます - Enumerable.Concat
のように:
var combined = foo.Concat(bar).Concat(baz)....;
つかいます - Enumerable.Concact
:
var query = foo.Concat(bar);
Concatと組み合わせたAggregateを常に使用できます...
var listOfLists = new List<List<int>>
{
new List<int> {1, 2, 3, 4},
new List<int> {5, 6, 7, 8},
new List<int> {9, 10}
};
IEnumerable<int> combined = new List<int>();
combined = listOfLists.Aggregate(combined, (current, list) => current.Concat(list)).ToList();
私が見る唯一の方法は、Concat()
を使用することです
_ var foo = new List<int> { 1, 2, 3 };
var bar = new List<int> { 4, 5, 6 };
var tor = new List<int> { 7, 8, 9 };
var result = foo.Concat(bar).Concat(tor);
_
しかし、より良いものを決める必要があります。
_var result = Combine(foo, bar, tor);
_
または
_var result = foo.Concat(bar).Concat(tor);
_
1つのポイントなぜConcat()
がより良い選択になるは、別の開発者にとってより明白になるということです。より読みやすく、シンプル。
Unionは次のように使用できます。
var combined=foo.Union(bar).Union(baz)...
ただし、これにより同一の要素が削除されるため、それらがある場合は、代わりにConcat
を使用することをお勧めします。
多数の個別のコレクションから始めることを考えると、あなたのソリューションはかなりエレガントだと思います。それらをつなぎ合わせるにはsomethingを実行する必要があります。
Combineメソッドから拡張メソッドを作成すると、構文上より便利になり、どこにいても使用できるようになります。
必要なのは、これだけですIEnumerable<IEnumerable<T>> lists
:
var combined = lists.Aggregate((l1, l2) => l1.Concat(l2));
これにより、lists
のすべてのアイテムが1つのIEnumerable<T>
(重複あり)。他の回答に記載されているように、Union
の代わりにConcat
を使用して重複を削除します。