2

EDIT: I split this to two questions:

  • Iterate over two lists ending at the shorter one
  • Iterate over several lists until the last element of the longest list has been reached

Assume I have two IEnumerable with many elements. Every IEnumerable has another type T.

IEnumerable<int> ints=getManyInts();
IEnumerable<string> strings=getSomeStrings();

What I want to do is to iterate over both lists, and get an item containing one int and one string for each step, until the end of the shortest list has been reached.

for(Item<int,string> item in Foo.Combine<int,string>(ints, strings))
{
    int i=item.Val1;
    string s=item.Val2;
}

You can also give me a hint how to do this in .NET 4.

matthias.lukaszek
  • 2,200
  • 1
  • 23
  • 33

5 Answers5

5

Hint for .NET 4.0:

var result = ints.Zip(strings, (i, s) => new { Key = i, Value = s });
foreach(var item in result)
{
    int key = item.Key;
    string value = item.Value;
    // Do something with the kvp
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
4

As non-LINQ-apprach (.NET 2) this can be done like this top iterate until one of the enumeration is finished:

using (IEnumerator<int> intItem = GetManyInts().GetEnumerator())
using (IEnumerator<string> stringItem = GetSomeStrings().GetEnumerator()) {
  while (intItem.MoveNext() && stringItem.MoveNext()) {
    int i=intItem.Current;
    string s=stringItem.Current;
  }
}

Edit (for your new condition), to iterate with default values until the last enumeration is done:

using (IEnumerator<int> intItem = GetManyInts().GetEnumerator())
using (IEnumerator<string> stringItem = GetSomeStrings().GetEnumerator()) {
  bool hasInt;
  bool hasString;
  while ((hasInt = intItem.MoveNext()) | (hasString = stringItem.MoveNext())) {
    int i=hasInt ? intItem.Current : default(int);
    string s=hasString ? stringItem.Current : default(string);
  }
}
Lucero
  • 59,176
  • 9
  • 122
  • 152
1

This can be done by manually doing what the for-each loop is doing internally

IEnumerable<int> ints=getManyInts();
IEnumerable<string> strings=getSomeStrings();
using (IEnumerator<int> intsEnum = ints.GetEnumerator())
using (IEnumerator<string> stringsEnum = strings.GetEnumerator())
{
    while (intsEnum.MoveNext() && stringsEnum.MoveNext())
    {
        int i = intsEnum.Current;
        string s = stringsEnum.Current;
    }
}

EDIT for longest list:

IEnumerable<int> ints=getManyInts();
IEnumerable<string> strings=getSomeStrings();
using (IEnumerator<int> intsEnum = ints.GetEnumerator())
using (IEnumerator<string> stringsEnum = strings.GetEnumerator())
{
    bool intIsValid = intsEnum.MoveNext()
    bool stringIsValid = stringsEnum.MoveNext()
    while (intIsValid || stringIsValid)
    {
        int i = default(int)
        string s = default(string)
        if(intIsValid)
        {
           i = intsEnum.Current;
           intIsValid = intsEnum.MoveNext();
        }
        if(stringIsValid)
        {
           s = stringsEnum.Current;
           stringIsValid = stringsEnum.MoveNext();
        }
        //code goes here
    }
}
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
1

Answered here: Iterate two Lists or Arrays with one ForEach statement in C#

Community
  • 1
  • 1
blueberryfields
  • 45,910
  • 28
  • 89
  • 168
0

I'm not sure that i understand the question / context.

Would using Dictionary work for you?

internal static class Foo
    {
        internal static Dictionary<TKey, TValue> Combine<TKey, TValue>
            ( IList<TKey> keys, IList<TValue> values )
        {
            var dictionary = new Dictionary<TKey, TValue>();
            // write your own 'combination' code...
            for (int i = 0; i < keys.Count && i<values.Count; i++)
            {
                dictionary.Add(keys[i], values[i]);
            }
            return dictionary;
        }
    }

    private static void Main(string[] args)
    {
        // collection initialization and var: .NET 3.0 or higher
        var keys = new List<int> {1, 2, 3, 5, 6, 7, 8, 10, 15, 99};
        var values = new List<string> {"one", "two", "tree", "four"};

        var combinded = Foo.Combine<int, string>(keys, values);
        foreach (KeyValuePair<int, string> keyValuePair in combinded)
        {
            int key = keyValuePair.Key;
            string value = keyValuePair.Value;
        }
    }
Simon Smeets
  • 581
  • 6
  • 17