2011-12-15 2 views
20

이 질문은 여러 번 전에 물어 봤지만 답변을 시도했지만 작동하지 않는 것 같습니다.하나의 foreach를 사용하여 같은 길이의 컬렉션 두 개를 반복하는 방법

같은 길이의 두 목록이 있지만 동일한 유형이 아니므로 list1 [i]가 list2 [i]와 연결되어있는 동안 동시에 두 항목을 반복하려고합니다.

예 :

내가

foreach(var listitem1, listitem2 in list1, list2) 
    { 
     //do stuff 
    } 

같은 soemthing이 possbile인가하고 싶은

(목록으로) 내가 (목록으로) 목록 1과리스트 2를 가지고 있다고 가정?

+0

무엇에 대한 첫 번째 foreach 내부의 두 번째 목록에 foreach가 있습니까? –

+0

Dupe : http : //stackoverflow.com/questions/5630758/how-to-loop-through-two-lists-simultaneously – Jonathan

+2

@Jonathan - VB.NET은 C#이 아니며 중복되지 않습니다. – Oded

답변

28

편집 - 순회 두 컬렉션에 같은 인덱스에 위치하는 동안 요구 사항이를 사용하려면 '동기화'방식으로 두 컬렉션을 통해 예를 이동하는 경우

두 번째 컬렉션의 첫 번째 요소가있는 첫 번째 컬렉션의 첫 번째 요소, 두 번째의 두 번째 요소 등을 포함하여 부작용 코드를 수행 할 필요없이 @sll's answer을 참조하고 .Zip()을 사용하여 동일한 인덱스에서 요소 쌍을 투영하고, 컬렉션 중 하나에서 요소가 없어 질 때까지

더 일반적으로 대신 foreach

, 당신은 GetEnumerator() 방법을 사용하여 두 컬렉션의 IEnumerable에서 IEnumerator에 액세스 할 수 있으며 당신이 다음 요소로 이동해야 할 때 다음 컬렉션 MoveNext() 전화 그 컬렉션. 이 기술은 두 개 이상의 정렬 된 스트림을 처리 할 때 스트림을 구체화 할 필요없이 일반적입니다. 컬렉션이 구체화하고 지원 색인, 이러한 ICollection 인터페이스로, 당신은 또한 첨자 [] 연산자를 사용할 수있는 경우이 요즘 오히려 서투른 느낌이 있지만 다른 사람이 지적했듯이

var stream1Enumerator = stream1.GetEnumerator(); 
var stream2Enumerator = stream2.GetEnumerator(); 
// i.e. Until stream1Enumerator runs out of 
while (stream1Enumerator.MoveNext()) 
{ 
    // Now you can iterate the collections independently 
    if (moon == 'Blue') 
    { 
     stream2Enumerator.MoveNext(); 
    } 
    // Do something with stream1Enumerator.Current and stream2Enumerator.Current 
} 

:

var smallestUpperBound = Math.Min(collection1.Count, collection2.Count); 
for (var index = 0; index < smallestUpperBound; index++) 
{ 
    // Do something with collection1[index] and collection2[index] 
} 

마지막으로 반환 된 요소의 인덱스 서수를 제공하는 overload of Linq's .Select()도 있는데 이는 유용 할 수도 있습니다.

아래의 대안으로 collection2의 처음 두 요소 collection1의 모든 요소를 ​​짝됩니다

var alternatePairs = collection1.Select(
    (item1, index1) => new 
    { 
     Item1 = item1, 
     Item2 = collection2[index1 % 2] 
    }); 
15

짧은 대답은 불가능합니다.

더 긴 응답은 foreach이 구문 설탕이므로 컬렉션에서 반복기를 가져오고 Next을 호출합니다. 2 개의 컬렉션에서는이 기능을 사용할 수 없습니다.

루프가 하나 뿐인 경우 for 루프를 사용하고 두 컬렉션에 동일한 인덱스 값을 사용할 수 있습니다.

for(int i = 0; i < collectionsLength; i++) 
{ 
    list1[i]; 
    list2[i]; 
} 

대안 (.NET 4.0 신규) LINQ Zip 연산자를 사용하여 하나에 모두 모음 병합 결과를 반복하는 것이다.

38

이 .NET 4 LINQ Zip() operator 또는 사용 열려 더 이전 .NET 버전에

MSDN에서 사용할 수 있도록뿐만 아니라 Zip() 연산자를 제공하는 소스 MoreLINQ library 사용 가능하다 :

int[] numbers = { 1, 2, 3, 4 }; 
string[] words = { "one", "two", "three" }; 

// The following example concatenates corresponding elements of the 
// two input sequences. 
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second); 
foreach (var item in numbersAndWords) 
{ 
    Console.WriteLine(item); 
} 

// OUTPUT: 
// 1 one 
// 2 two 
// 3 three 

에게 유용한 링크 :

+0

http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx – Hammerstein

+0

@ 해머 슈타인 : 참 좋은 기사 – sll

2

foreach 대신 for()를 사용하지 않는 이유는 무엇입니까? 예를 들어 ...

int length = list1.length; 
for(int i = 0; i < length; i++) 
{ 
    // do stuff with list1[i] and list2[i] here. 
} 
4
foreach(var tup in list1.Zip(list2, (i1, i2) => Tuple.Create(i1, i2))) 
{ 
    var listItem1 = tup.Item1; 
    var listItem2 = tup.Item2; 
    /* The "do stuff" from your question goes here */ 
} 

그것은 비록 같은 수 수 많은 당신의 여기를 생성 람다에 갈 수있다 "물건을" 튜플이 더 좋을 것입니다.

컬렉션이 반복 될 수있는 경우 for() 루프가 여전히 단순합니다.

업데이트 : 이제와 우리가 사용할 수있는 내장의 C# 7.0의 ValueTuple에 대한 지원 :

foreach ((var listitem1, var listitem2) in list1.Zip(list2, (i1, i2) => (i1, i2))) 
{ 
    /* The "do stuff" from your question goes here */ 
} 
0

당신은 헬퍼 클래스에서> 두 IEnumerable을 <을 포장 할 수 있습니다

var nums = new []{1, 2, 3}; 
var strings = new []{"a", "b", "c"}; 

ForEach(nums, strings).Do((n, s) => 
{ 
    Console.WriteLine(n + " " + s); 
}); 

//----------------------------- 

public static TwoForEach<A, B> ForEach<A, B>(IEnumerable<A> a, IEnumerable<B> b) 
{ 
    return new TwoForEach<A, B>(a, b); 
} 

public class TwoForEach<A, B> 
{ 
    private IEnumerator<A> a; 
    private IEnumerator<B> b; 

    public TwoForEach(IEnumerable<A> a, IEnumerable<B> b) 
    { 
    this.a = a.GetEnumerator(); 
    this.b = b.GetEnumerator(); 
    } 

    public void Do(Action<A, B> action) 
    { 
    while (a.MoveNext() && b.MoveNext()) 
    { 
     action.Invoke(a.Current, b.Current); 
    } 
    } 
} 
관련 문제