Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
633 views
in Technique[技术] by (71.8m points)

c# - Combine entries from two lists by position using LINQ

Say I have two lists with following entries

List<int> a = new List<int> { 1, 2, 5, 10 };
List<int> b = new List<int> { 6, 20, 3 };

I want to create another List c where its entries are items inserted by position from two lists. So List c would contain the following entries:

List<int> c = {1, 6, 2, 20, 5, 3, 10}

Is there a way to do it in .NET using LINQ? I was looking at .Zip() LINQ extension, but wasn't sure how to use it in this case.

Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To do it using LINQ, you can use this piece of LINQPad example code:

void Main()
{
    List<int> a = new List<int> { 1, 2, 5, 10 };
    List<int> b = new List<int> { 6, 20, 3 };

    var result = Enumerable.Zip(a, b, (aElement, bElement) => new[] { aElement, bElement })
        .SelectMany(ab => ab)
        .Concat(a.Skip(Math.Min(a.Count, b.Count)))
        .Concat(b.Skip(Math.Min(a.Count, b.Count)));

    result.Dump();
}

Output:

LINQPad example output

This will:

  • Zip the two lists together (which will stop when either runs out of elements)
  • Producing an array containing the two elements (one from a, another from b)
  • Using SelectMany to "flatten" this out to one sequence of values
  • Concatenate in the remainder from either list (only one or neither of the two calls to Concat should add any elements)

Now, having said that, personally I would've used this:

public static IEnumerable<T> Intertwine<T>(this IEnumerable<T> a, IEnumerable<T> b)
{
    using (var enumerator1 = a.GetEnumerator())
    using (var enumerator2 = b.GetEnumerator())
    {
        bool more1 = enumerator1.MoveNext();
        bool more2 = enumerator2.MoveNext();

        while (more1 && more2)
        {
            yield return enumerator1.Current;
            yield return enumerator2.Current;

            more1 = enumerator1.MoveNext();
            more2 = enumerator2.MoveNext();
        }

        while (more1)
        {
            yield return enumerator1.Current;
            more1 = enumerator1.MoveNext();
        }

        while (more2)
        {
            yield return enumerator2.Current;
            more2 = enumerator2.MoveNext();
        }
    }
}

Reasons:

  • It doesn't enumerate a nor b more than once
  • I'm skeptical about the performance of Skip
  • It can work with any IEnumerable<T> and not just List<T>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...