What is a template for listing two lists at once, without an index?

I am looking for an ad template to list two IEnumerable <> synchronized.

If I were to do something and add C # syntax, I could write:

foreach(var firstItem, var secondItem in this.ListOne, this.ListTwo) { if (firstItem.Prop == secondItem.Prop) WorkSomeMagic(secondItem); DoSomethingElse(firstItem); } 

Now, obviously, this does not exist. What patterns did people use to achieve something similar when dealing with enumerations not accessible by the index? Keep in mind that what is inside my pseudo-foreach would be more complex; I am simplified for an example.

+6
c #
source share
5 answers

You are looking for Zip, which is new in .NET 4, or you can use the implementation here:

Is there a .Net format method in the mailbox?

+9
source share

I usually do the following:

 using (IEnumerator<int> e1 = this.ListOne.GetEnumerator(), e2 = this.ListTwo.GetEnumerator()) { while (e1.MoveNext() && e2.MoveNext()) { ... } } 

Or write an extension method:

 public static void EnumerateWith<T>(this IEnumerable<T> left, IEnumerable<T> right, Action<T,T> del) { using (IEnumerator<T> l = left.GetEnumerator(), r = right.GetEnumerator()) { while (l.MoveNext() && r.MoveNext()) { del(l.Current,r.Current); } } } ListOne.EnumerateWith(ListTwo, (left, right) => { ... }); 
+7
source share

As with any general C # question, this will probably have 10 good answers posted before the VS2008 even loads. Instead of this rat race, I’ll come up with an unusual “anti-pattern” that you should never use. In fact, someone is writing a critical mission code, please stop reading now.

 using System; using System.Collections.Generic; using System.Linq; class EnumTwoLists { static void Main(string[] args) { var left = new List<int>(); var right = new List<DateTime>(); var demo = new LinqAbuse<int, DateTime>(left, right); demo.Populate(40, s => s * s, d => new DateTime(2009, d / 31 + 1, d % 31 + 1)); demo.Enumerate( (s, d) => Console.WriteLine(String.Format("Executing arbitrary code with {0} and {1}", s, d)) ); } } class LinqAbuse<T1, T2> { public LinqAbuse(List<T1> l, List<T2> r) { left = l; right = r; } List<T1> left; List<T2> right; public void Populate(int size, Func<int, T1> leftGenerator, Func<int, T2> rightGenerator) { new int[size].Aggregate(0, (index, empty) => PopulateWrapper(left, right, leftGenerator, rightGenerator, index)); } int PopulateWrapper(List<T1> left, List<T2> right, Func<int, T1> leftGenerator, Func<int, T2> rightGenerator, int index) { left.Add(leftGenerator(index)); right.Add(rightGenerator(index)); return ++index; } public void Enumerate(Action<T1, T2> loopBody) { left.Join(right, l => "", r => "", (l, r) => ActionWrapper(l, r, loopBody), new CartesianComparer<object>(right.Count)) .ToList(); } object ActionWrapper(T1 x, T2 y, Action<T1, T2> action) { action(x, y); return null; } } class CartesianComparer<T> : IEqualityComparer<T> { public CartesianComparer(int _size) { size = _size; equalsCounter = (size * (size - 1) >> 1) + size; // Combinations(size, 2) + (size - trueCounter) } private int size; private int equalsCounter; private int trueCounter = 0; public bool Equals(T x, T y) { if (0 < --equalsCounter) return false; equalsCounter = size - ++trueCounter; return true; } public int GetHashCode(T obj) { return 0; } } 

Isn't she pretty? (alternative headline: mom, why is Anders crying?)

+2
source share

Ignoring zeros checks and something else:

 IEnumerable<T1> first; IEnumerable<T2> second; using (IEnumerator<T1> e1 = first.GetEnumerator()) { using (IEnumerator<T2> e2 = second.GetEnumerator()) { while (e1.MoveNext() && e2.MoveNext()) { // do something eith e1.Current and e2.Current } } 

}

0
source share

I know this question is old, but for those who come to this question, now you can build Jason 's answer and JaredPar's answer with C # 7 ValueTuple , which will give you a syntax similar to the original question. You may need to install the nuget System.ValueTuple package.

If you declare an extension method as follows:

 internal static class EnumerableExtensions { internal static IEnumerable<(T1, T2)> EnumerateWith<T1, T2>(this IEnumerable<T1> first, IEnumerable<T2> second) { using (var firstEnumerator = first.GetEnumerator()) using (var secondEnumerator = second.GetEnumerator()) { while(firstEnumerator.MoveNext() && secondEnumerator.MoveNext()) { yield return (firstEnumerator.Current, secondEnumerator.Current); } } } } 

Then you can use it as follows:

 List<Foo> foos = new List<Foo>() { new Foo(), new Foo(), new Foo() }; List<Bar> bars = new List<Bar>() { new Bar(), new Bar(), new Bar() }; foreach((Foo foo, Bar bar) in foos.EnumerateWith(bars)) { Console.WriteLine(foo.ID); Console.WriteLine(bar.ID); } 
0
source share

All Articles