How to take each of two elements from IEnumerable as a pair?

I have IEnumerable<string>one that looks like {"First", "1", "Second", "2", ... }.

I need to iterate through the list and create IEnumerable<Tuple<string, string>>where the Tuples will look like this:

"First", "1"

"Second", "2"

So, I need to create pairs from the list that I should get as above.

+3
source share
6 answers

You can do something like:

var pairs = source.Select((value, index) => new {Index = index, Value = value})
                  .GroupBy(x => x.Index / 2)
                  .Select(g => new Tuple<string, string>(g.ElementAt(0).Value, 
                                                         g.ElementAt(1).Value));

It will give you IEnumerable<Tuple<string, string>>. It works by grouping elements by odd / even positions, and then expanding each group to Tuple. The advantage of this approach over the approach Zipproposed by BrokenGlass is that it only lists the original enumerated time .

- , - (.. linq), , .

+4

:

public static IEnumerable<Tuple<T, T>> Tupelize<T>(this IEnumerable<T> source)
{
    using (var enumerator = source.GetEnumerator())
        while (enumerator.MoveNext())
        {
            var item1 = enumerator.Current;

            if (!enumerator.MoveNext())
                throw new ArgumentException();

            var item2 = enumerator.Current;

            yield return new Tuple<T, T>(item1, item2);
        }
}

, , . 2:

public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> list, int batchSize)
{

    var batch = new List<T>(batchSize);

    foreach (var item in list)
    {
        batch.Add(item);
        if (batch.Count == batchSize)
        {
            yield return batch;
            batch = new List<T>(batchSize);
        }
    }

    if (batch.Count > 0)
        yield return batch;
}

:

var tuples = items.Chunk(2)
    .Select(x => new Tuple<string, string>(x.First(), x.Skip(1).First()))
    .ToArray();

, :

var tuples = items.Where((x, i) => i % 2 == 0)
    .Zip(items.Where((x, i) => i % 2 == 1), 
                     (a, b) => new Tuple<string, string>(a, b))
    .ToArray();
+10

, .Zip():

IEnumerable<string> source = new List<string> { "First", "1", "Second", "2" };
var tupleList = source.Zip(source.Skip(1), 
                           (a, b) => new Tuple<string, string>(a, b))
                      .Where((x, i) => i % 2 == 0)
                      .ToList();

, , , - ( "," 1 "), (" 1 "," ",), (" "," 2").

, ( "," 1 "), (" "," 2 ") ..

Edit:

- , "" - , ( ) :

  • : - , Enumerables, , .

  • : , - - , 1.

, , , foreach, , for, .

+4

morelinq Batch , , :

var str = new string[] { "First", "1", "Second", "2", "Third", "3" };
var tuples = str.Batch(2, r => new Tuple<string, string>(r.FirstOrDefault(), r.LastOrDefault()));
+4
IEnumerable<T> items = ...;
using (var enumerator = items.GetEnumerator())
{
    while (enumerator.MoveNext())
    {
        T first = enumerator.Current;
        bool hasSecond = enumerator.MoveNext();
        Trace.Assert(hasSecond, "Collection must have even number of elements.");
        T second = enumerator.Current;

        var tuple = new Tuple<T, T>(first, second);
        //Now you have the tuple
    }
}
+1

.NET 4.0, tuple (. http://mutelight.org/articles/finally-tuples-in-c-sharp.html). LINQ , . , , , , , , , "First:1", "Second:2", ( LINQ).

0

All Articles