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 ?

3
  • why would you want that? Commented Jul 10, 2012 at 9:46
  • 2
    stackoverflow.com/questions/1955766/… Commented Jul 10, 2012 at 9:46
  • 1
    you can't do it in a simple and efficient way. the for loop looks fine but use a stringbuilder Commented Jul 10, 2012 at 9:48

7 Answers 7

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;
}
Sign up to request clarification or add additional context in comments.

6 Comments

Out of curiosity, what would happen if listB is shorter than listA ?
@Alex I believe it stops iterating on the shortest enumerable. The linked documentation above confirms this in the remarks.
@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."
I'd +2 this one if I could ... shame on me for not researching the lanuage properly, I wasn't aware of this extension
i try that but listA.Zip is not in c#. zip erroe
|
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.

Comments

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();
}

Comments

1

Use LINQ

string text = listA.Zip(listB, (a, b) => new {A = a, B = b}).Aggregate("", (current, pair) => current + (pair.A + " and " + pair.B));

Comments

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.

Comments

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

1 Comment

This is simply a rehash of the duplicate question mentioned in the comments.
-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

6 Comments

why are you using listA[cnt] instead of i?
@Francesco don't you see that the i is a string variable and we can't access an array index using string.
@FrancescoBaruchelli can we access an array index using string?
yes, it's a string, and listA[cnt] is ...? I mean, why are you wasting time accessing an array to get what you already have?
@FrancescoBaruchelli but if i won't fetch it index wise in foreach block so how can i concatenate both the string like A1 and B1, A2 and B2..
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.