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
448 views
in Technique[技术] by (71.8m points)

c# - Merge multiple Lists into one List with LINQ

Is there a slick way to merge multiple Lists into a single List using LINQ to effectively replicate this?

public class RGB
{
    public int Red { get; set; }
    public int Green { get; set; }
    public int Blue { get; set; }
    public RGB(int red, int green, int blue) { Red = red; Green = green; Blue = blue; }
}

public void myFunction()
{
    List<int> red = new List<int> { 0x00, 0x03, 0x06, 0x08, 0x09 };
    List<int> green = new List<int> { 0x00, 0x05, 0x06, 0x07, 0x0a };
    List<int> blue = new List<int> { 0x00, 0x02, 0x03, 0x05, 0x09 };

    List<RGB> colors = new List<RGB>();

    colors.Add(new RGB(red[0], green[0], blue[0]));
    colors.Add(new RGB(red[1], green[1], blue[1]));
    colors.Add(new RGB(red[2], green[2], blue[2]));
    colors.Add(new RGB(red[3], green[3], blue[3]));
    colors.Add(new RGB(red[4], green[4], blue[4]));
}

Or, since the lists arrive separately, its more effective to merge them sequentially like the following.

public class RGB
{
    public int Red { get; set; }
    public int Green { get; set; }
    public int Blue { get; set; }

    public RGB(int red, int green, int blue) { Red = red; Green = green; Blue = blue; }
}

public void myFunction()
{
    List<int> red = new List<int> { 0x00, 0x03, 0x06, 0x08, 0x09 };

    List<RGB> colors = new List<RGB>();

    colors.Add(new RGB(red[0], 0, 0));
    colors.Add(new RGB(red[1], 0, 0));
    colors.Add(new RGB(red[2], 0, 0));
    colors.Add(new RGB(red[3], 0, 0));
    colors.Add(new RGB(red[4], 0, 0));

    List<int> green = new List<int> { 0x00, 0x05, 0x06, 0x07, 0x0a };

    colors[0].Green = green[0];
    colors[1].Green = green[1];
    colors[2].Green = green[2];
    colors[3].Green = green[3];
    colors[4].Green = green[4];

    List<int> blue = new List<int> { 0x00, 0x02, 0x03, 0x05, 0x09 };

    colors[0].Blue = blue[0];
    colors[1].Blue = blue[1];
    colors[2].Blue = blue[2];
    colors[3].Blue = blue[3];
    colors[4].Blue = blue[4];
}
See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

You're essentially trying to zip up three collections. If only the LINQ Zip() method supported zipping up more than two simultaneously. But alas, it only supports only two at a time. But we can make it work:

var reds = new List<int> { 0x00, 0x03, 0x06, 0x08, 0x09 };
var greens = new List<int> { 0x00, 0x05, 0x06, 0x07, 0x0a };
var blues = new List<int> { 0x00, 0x02, 0x03, 0x05, 0x09 };

var colors =
    reds.Zip(greens.Zip(blues, Tuple.Create),
        (red, tuple) => new RGB(red, tuple.Item1, tuple.Item2)
    )
    .ToList();

Of course it's not terribly painful to write up an extension method to do three (or more).

public static IEnumerable<TResult> Zip<TFirst, TSecond, TThird, TResult>(
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    IEnumerable<TThird> third,
    Func<TFirst, TSecond, TThird, TResult> resultSelector)
{
    using (var enum1 = first.GetEnumerator())
    using (var enum2 = second.GetEnumerator())
    using (var enum3 = third.GetEnumerator())
    {
        while (enum1.MoveNext() && enum2.MoveNext() && enum3.MoveNext())
        {
            yield return resultSelector(
                enum1.Current,
                enum2.Current,
                enum3.Current);
        }
    }
}

This makes things a lot more nicer:

var colors =
    reds.Zip(greens, blues,
        (red, green, blue) => new RGB(red, green, blue)
    )
    .ToList();

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

...