2012-04-24 2 views
19

저는 3 개가 있습니다 (3 ~ 4 개 이상의 일반 목록을 가질 수 있지만이 예제에서는 3 개) 일반 목록을 갖습니다.C# Zip에서 두 개 이상의 일반 목록을 결합하는 방법은 무엇입니까?

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 
} 

세에 대한 우편으로 simmilary 사용 방법 :

나는 ZIP 두 목록을 결합하는 것을 사용 목록?

감사

편집 : 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

[아이템을 3 개 모음에서 만들려면 Linq을 사용하십시오] (http://stackoverflow.com/questions/5284315/create-items-from-3-collections-using-linq) – ensisNoctis

답변

16

가장 확실한 방법은 Zip을 두 번 사용하는 것입니다. 예를 들어

,

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

는 결합 (추가) 세 List<int> 객체의 요소 것입니다.

업데이트 :

당신은과 같이 세 가지 IEnumerable들과 함께 Zip 같은 역할을하는 새로운 확장 방법을 정의 할 수 있습니다 :

지금
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); 
     } 
    } 
} 

(위와 같은 맥락에서) 사용법 다음과 같이됩니다 :

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

마찬가지로 세 개의 목록을 다음과 결합 할 수 있습니다.

+0

가능한 한 좋은 방법입니다. 'foreach' 문을 사용하여 각 요소의 값을 얻고 싶기 때문에 (x, y) 변수를 사용합니다 –

+0

EDITED 게시물을 살펴볼 수 있습니까? 고마워요 –

+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

쪽지 : [Tuple.Create] (https://msdn.microsoft.com/en-us/library/dd383822(v=vs.110).aspx)를 사용하는 것이 더 쉽습니다. 일반 매개 변수를 지정해야합니다. – 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하는 것이 좋습니다.

재미있게 보내세요!

관련 문제