3
List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };

for(int i = 0; i < listA.Count; i++)
{
    text += listA[i] + " and " + listB[i];
}

How can I do this using a foreach loop ?

Alex
  • 23,004
  • 4
  • 39
  • 73
Hina Hanif
  • 39
  • 1
  • 1
  • 3

7 Answers7

14

You can use Linq and the Zip method:

List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };

foreach (var pair in listA.Zip(listB, (a,b) => new {A = a, B = b}))
{
    text += pair.A + " and " + pair.B;
}
nemesv
  • 138,284
  • 16
  • 416
  • 359
  • Out of curiosity, what would happen if listB is shorter than listA ? – Alex Jul 10 '12 at 09:50
  • @Alex I believe it stops iterating on the shortest enumerable. The linked documentation above confirms this in the remarks. – Adam Houldsworth Jul 10 '12 at 09:51
  • 1
    @Alex from msdn: "If the input sequences do not have the same number of elements, the method combines elements until it reaches the end of one of the sequences. For example, if one sequence has three elements and the other one has four, the result sequence has only three elements." – nemesv Jul 10 '12 at 09:52
  • I'd +2 this one if I could ... shame on me for not researching the lanuage properly, I wasn't aware of this extension – Alex Jul 10 '12 at 09:52
  • i try that but listA.Zip is not in c#. zip erroe – Hina Hanif Jul 10 '12 at 10:00
  • @HinaHanif Zip is an extension method introduced in .net 3.5 you need to using it's namspace: so add this line to your source file: `using System.Linq;` – nemesv Jul 10 '12 at 10:19
4

You cannot do this with a foreach any better than you are already doing it with for -- foreach is really only designed to work well when there is only one sequence to enumerate.

However, you can do it very conveniently with LINQ:

text = string.Join("", listA.Zip(listB, (a, b) => a + " and " + b));

This requires .NET 4 both for Zip and for the specific overload of string.Join.

Jon
  • 428,835
  • 81
  • 738
  • 806
4

Another way of doing this is doing that with simple Enumerator:

IEnumerator<string>  enumerator = listB.GetEnumerator(); 
enumerator.MoveNext();
foreach(var stra in listA) {
    text += stra + " and " + enumerator.Current.ToString() + ", ";
    enumerator.MoveNext();
}
Tigran
  • 61,654
  • 8
  • 86
  • 123
1

Use LINQ

string text = listA.Zip(listB, (a, b) => new {A = a, B = b}).Aggregate("", (current, pair) => current + (pair.A + " and " + pair.B));
Ria
  • 10,237
  • 3
  • 33
  • 60
1

And if you do not want to use LINQ and you want them to iterate parallel you have few options - with new classes etc. like below OR you can use foreach, but only for one of the lists, like this:

List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };
string text = "";
int i = 0;
foreach (string s in listA) {
   text += s + " and " + listB [i++] + "\n";
}
Console.WriteLine (text);

or make it a bit nicer using GetEnumerator:

List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };
string text = "";       
List<string>.Enumerator e = listB.GetEnumerator ();
foreach (string s in listA) {
   e.MoveNext ();
   text += s + " and " + e.Current + "\n";
}
Console.WriteLine (text);

also you can create yourself an Enumberable metacollection which will return out of that always a simple string array - for that you will need to create an Enumerator and a class which is derieves from IEnumerable:

First the Enumerator:

private class DoubleStringEnumerator : IEnumerator
{
    private DoubleString _elemList;
    private int _index;
    public DoubleStringEnumerator(DoubleString doubleStringObjt)
    {
        _elemList = doubleStringObjt;
        _index = -1;
    }
    public void Reset()
    {
        _index = -1;
    }
    public object Current {
        get {
            return _elemList.getNext();
        }
    }
    public bool MoveNext ()
    {
        _index++;
        if (_index >= _elemList.Length)
            return false;
        else
            return true;
    }
}

The Current method does not really reflects it's name in the given example - but it is for learning purposes.

Now the class:

public class DoubleString : IEnumerable
{
    public int Length;
    List<String> listA;
    List<String> listB;
    List<string>.Enumerator eA,eB;
    public DoubleString(List<String> newA,List<String> newB)
    {
        if(newA.Count != newB.Count) {
            throw new Exception("Lists lengths must be the same");    
        }
        listA = newA;
        listB = newB;
        eA = listA.GetEnumerator ();
        eB = listB.GetEnumerator ();
        Length = listA.Count;
    }
    IEnumerator IEnumerable.GetEnumerator ()
    {
        return (IEnumerator)new DoubleStringEnumerator(this);
    }
    public string[] getNext ()
    {
        eA.MoveNext ();
        eB.MoveNext ();
        return new string[] {eA.Current ,eB.Current };
    }
}

And the code itself:

List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };               
DoubleString newDoubleString = new DoubleString (listA, listB);             
string text = "";
foreach (string[] s in newDoubleString) {
    text += s[0] + " and " + s[1] + "\n";
}
Console.WriteLine (text);

Of course still better to use LINQ. The code is not optimsied, but I had no compiler with me so writting from my head - hope it will clarify few things. Feel free to ask questions.

Bartosz Pachołek
  • 1,278
  • 1
  • 8
  • 17
-2
List<int> = new [] { 1, 2, 3, 4 };
List<String> words = new [] { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w });
foreach(var nw in numbersAndWords)
{
    Console.WriteLine(nw.Number + nw.Word);
}
patel.milanb
  • 5,822
  • 15
  • 56
  • 92
-3

Here is the solution using foreach:

string text = null;
int cnt = 0;

List<String> listA = new List<string> { "A1", "A2" };
List<String> listB = new List<string> { "B1", "B2" };

foreach (string i in listA)
  {
         text += listA[cnt] + " and " + listB[cnt];
         cnt++;
  }

Thanks & Regards,
Subhankar

Subhankar
  • 126
  • 6