2012-04-24 6 views
19

私は3つ持っています(3つ以上の一般的なリストを持つことは可能ですが、この例では3つの一般的なリストにします)。C#Zipで2つ以上の汎用リストを結合するにはどうすればよいですか?

List<string> list1 

List<string> list2 

List<string> list3 

すべてのリストの要素数は同じです(同じ数)。

foreach(var item in result){ 
Console.WriteLine(item.test1 + " " + item.test2); 
} 

のように、私はforeach文に対して、各リストをforeach避けるためにすることを使用

var result = list1.Zip(list2, (a, b) => new { 
    test1 = f, 
    test2 = b 
} 

3用のジップとsimmilary使用方法:

私はZIPで二つのリストを結合することを使用しましたリスト?

おかげ

EDIT:ZIP後

List<string> list1 = new List<string>{"test", "otherTest"}; 

List<string> list2 = new List<string>{"item", "otherItem"}; 

List<string> list3 = new List<string>{"value", "otherValue"}; 

(私は方法を知っていない)、私は(結果にしたいVS2010のデバッグモードで:私が好きたい

[0] { a = {"test"}, 
     b = {"item"}, 
     c = {"value"} 
    } 

[1] { a = {"otherTest"}, 
     b = {"otherItem"}, 
     c = {"otherValue"} 
    } 

どうやって?

+0

「[Linqを使って3つのコレクションからアイテムを作成する]」(http://stackoverflow.com/questions/5284315/create-items-from-3-collections-using-linq) – ensisNoctis

答えて

16

私にとって最も明白な方法は、Zipを2回使用することです。例えば

var results = l1.Zip(l2, (x, y) => x + y).Zip(l3, (x, y) => x + y); 

は(追加)は、3つのList<int>オブジェクトの要素を組み合わせることになります。

アップデート:今

public static class MyFunkyExtensions 
{ 
    public static IEnumerable<TResult> ZipThree<T1, T2, T3, TResult>(
     this IEnumerable<T1> source, 
     IEnumerable<T2> second, 
     IEnumerable<T3> third, 
     Func<T1, T2, T3, TResult> func) 
    { 
     using (var e1 = source.GetEnumerator()) 
     using (var e2 = second.GetEnumerator()) 
     using (var e3 = third.GetEnumerator()) 
     { 
      while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) 
       yield return func(e1.Current, e2.Current, e3.Current); 
     } 
    } 
} 

(上記と同じ文脈で)使用:

あなたはそうのように、3 IEnumerable秒でZipのような役割を果たし、新たな拡張メソッドを定義することができます

var results = l1.ZipThree(l2, l3, (x, y, z) => x + y + z); 

同様に、次の3つのリストを組み合わせることができます:

+0

これを行うには良い方法です私は 'foreach'文に使用して、各要素から値を取得したいので、(x、y)を変数と –

+0

編集したポストの上に見てみることはできますか?ありがとうございます –

+0

私は私の答えを更新しました。私はこれがあなたの必要とすることを望みます。 – GolfWolf

2
class Program 
{ 
    static void Main(string[] args) 
    { 
     List<string> list1 = new List<string> { "test", "otherTest" }; 
     List<string> list2 = new List<string> { "item", "otherItem" }; 
     List<string> list3 = new List<string> { "value", "otherValue" }; 

     var result = CombineListsByLayers(list1, list2, list3); 
    } 

    public static List<string>[] CombineListsByLayers(params List<string>[] sourceLists) 
    { 
     var results = new List<string>[sourceLists[0].Count]; 

     for (var i = 0; i < results.Length; i++) 
     { 
      results[i] = new List<string>(); 
      foreach (var sourceList in sourceLists) 
       results[i].Add(sourceList[i]); 
     } 
     return results; 
    } 
+0

時々葉巻は単に葉巻のままであるべきです。 –

+0

私はあなたの質問に対するより良い答えである他の答えを読んだ。 正直なところ、なぜ読めないと書くことがX10の倍以上かかる気にいらないために行きますか? –

+0

私は正しく質問を読むときに役立ちます:)、私から+1。サイドノートで – Phil

2

var results = list1.ZipThree(list2, list3, (a, b, c) => new { a, b, c }); 
あなたはカスケードジップ方法と匿名クラスとタプル結果とC#で多くのリストを組み合わせることができます。

List<string> list1 = new List<string> { "test", "otherTest" }; 
List<string> list2 = new List<string> { "item", "otherItem" }; 
List<string> list3 = new List<string> { "value", "otherValue" }; 

IEnumerable<Tuple<string, string, string>> result = list1 
    .Zip(list2, (e1, e2) => new {e1, e2}) 
    .Zip(list3, (z1, e3) => Tuple.Create(z1.e1, z1.e2, e3)); 

結果は次のとおりです。

[0] 
{(test, item, value)} 
    Item1: "test" 
    Item2: "item" 
    Item3: "value" 
+2

:あなたがいない(.aspxの)https://msdn.microsoft.com/en-us/library/dd383822(V = vs.110)[Tuple.Create]を使用する方が簡単ですジェネリックパラメータを指定する必要があります。 – Maarten

2

私の知る別の非常に興味深いソリューションがあります。これは主に教育的観点からは興味深いですが、リストの数をさまざまに変えて実行する必要がある場合は、便利かもしれません。

このメソッドは、LINQのクエリ構文を使用する際に慣例によって取得され、.NETのLINQ SelectMany機能を無効にします。標準SelectMany実装は、デカルト積を行う。上書きされたものは、代わりにジップを行うことができます。実際の実装は次のようになります。

static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, 
     Func<TSource, IEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> select) 
{ 
    using (var e1 = source.GetEnumerator()) 
     using (var e2 = selector(default(TSource)).GetEnumerator()) 
      while (true) 
       if (e1.MoveNext() && e2.MoveNext()) 
        yield return select(e1.Current, e2.Current); 
       else 
        yield break; 
} 

それは少し怖いに見えますが、それは、一度書き込んだ場合ビュンのロジックで、多くの場所で使用すると、クライアントのコードはかなり見栄えすることができます - あなたは、任意の数を圧縮することができますIEnumerable<T>標準のLINQクエリの構文を使用して:あなたが実行した場合

var titles = new string[] { "Analyst", "Consultant", "Supervisor"}; 
var names = new string[] { "Adam", "Eve", "Michelle" }; 
var surnames = new string[] { "First", "Second", "Third" }; 

var results = 
    from title in titles 
    from name in names 
    from surname in surnames 
    select $"{ title } { name } { surname }"; 

を:

foreach (var result in results) 
    Console.WriteLine(result); 

をあなたが取得します:

Analyst Adam First 
Consultant Eve Second 
Supervisor Michelle Third 

そうでなければ、根本的に、周囲のコードの動作を変更しますので、あなたは、あなたのクラス内のプライベートこの拡張機能を維持する必要があります。また、新しい型は、IEnumerablesの標準LINQビヘイビアとは区別されないように便利です。私は、この拡張メソッド+いくつかの利点で一度小さなC#プロジェクトを作成した教育目的のために

:あなたはこの興味深いを見つけた場合https://github.com/lukiasz/Zippableまた

、私は強くJon Skeet's Reimplementing LINQ to Objects articlesをお勧めします。

は、お楽しみに!