C# 使用LINQ将多个列表合并为一个列表
有没有一种巧妙的方法可以使用LINQ将多个列表合并成一个列表来有效地复制它C# 使用LINQ将多个列表合并为一个列表,c#,linq,design-patterns,C#,Linq,Design Patterns,有没有一种巧妙的方法可以使用LINQ将多个列表合并成一个列表来有效地复制它 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 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]));
}
公共类RGB
{
公共整数Red{get;set;}
公共整数绿色{get;set;}
公共整数蓝色{get;set;}
公共RGB(整数红色、整数绿色、整数蓝色){红色=红色;绿色=绿色;蓝色=蓝色;}
}
公共函数()
{
列表红色=新列表{0x00,0x03,0x06,0x08,0x09};
绿色列表=新列表{0x00,0x05,0x06,0x07,0x0a};
列表蓝色=新列表{0x00,0x02,0x03,0x05,0x09};
列表颜色=新列表();
添加(新的RGB(红色[0],绿色[0],蓝色[0]);
添加(新的RGB(红色[1],绿色[1],蓝色[1]);
添加(新的RGB(红色[2],绿色[2],蓝色[2]);
添加(新的RGB(红色[3],绿色[3],蓝色[3]);
添加(新的RGB(红色[4],绿色[4],蓝色[4]);
}
或者,由于列表是单独到达的,所以按如下顺序合并它们更有效
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];
}
公共类RGB
{
公共整数Red{get;set;}
公共整数绿色{get;set;}
公共整数蓝色{get;set;}
公共RGB(整数红色、整数绿色、整数蓝色){红色=红色;绿色=绿色;蓝色=蓝色;}
}
公共函数()
{
列表红色=新列表{0x00,0x03,0x06,0x08,0x09};
列表颜色=新列表();
添加(新的RGB(红色[0],0,0));
添加(新的RGB(红色[1],0,0));
添加(新的RGB(红色[2],0,0));
添加(新的RGB(红色[3],0,0));
添加(新的RGB(红色[4],0,0));
绿色列表=新列表{0x00,0x05,0x06,0x07,0x0a};
颜色[0]。绿色=绿色[0];
颜色[1]。绿色=绿色[1];
颜色[2]。绿色=绿色[2];
颜色[3]。绿色=绿色[3];
颜色[4]。绿色=绿色[4];
列表蓝色=新列表{0x00,0x02,0x03,0x05,0x09};
颜色[0]。蓝色=蓝色[0];
颜色[1]。蓝色=蓝色[1];
颜色[2]。蓝色=蓝色[2];
颜色[3]。蓝色=蓝色[3];
颜色[4]。蓝色=蓝色[4];
}
是-您可以这样做:
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 = Enumerable
.Range(0, red.Count)
.Select(i => new RGB(red[i], green[i], blue[i]))
.ToList();
List_A.Select(a => a.List_B).SelectMany(s => s).ToList();
List red=新列表{0x00、0x03、0x06、0x08、0x09};
绿色列表=新列表{0x00,0x05,0x06,0x07,0x0a};
列表蓝色=新列表{0x00,0x02,0x03,0x05,0x09};
列表颜色=可枚举
.范围(0,红色.计数)
.选择(i=>新RGB(红色[i],绿色[i],蓝色[i]))
.ToList();
您实际上是在尝试压缩三个集合。如果只有LINQZip()
方法支持同时压缩两个以上的文件。但遗憾的是,它一次只能支持两个。但我们可以做到:
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();
您可以使用Aggregate with Zip一次性压缩任意数量的IEnumerable 以下是您可以通过示例实现的方法:
var colorLists = new List<int>[] { red, green, blue };
var rgbCount = red.Count;
var emptyTriples =
Enumerable.Repeat<Func<List<int>>>(() => new List<int>(), rgbCount)
.Select(makeList => makeList());
var rgbTriples = colorLists.Aggregate(
emptyTriples,
(partialTriples, channelValues) =>
partialTriples.Zip(
channelValues,
(partialTriple, channelValue) =>
{
partialTriple.Add(channelValue);
return partialTriple;
}));
var rgbObjects = rgbTriples.Select(
triple => new RGB(triple[0], triple[1], triple[2]));
var colorLists=新列表[]{red,green,blue};
var rgbCount=红色。计数;
var空字符=
可枚举。重复(()=>new List(),rgbCount)
.Select(makeList=>makeList());
var rgbTriples=colorLists.Aggregate(
空白的文字,
(partialTriples、ChannelValue)=>
部分三角帆,拉链(
渠道价值观,
(partialTriple,channelValue)=>
{
partialTriple.Add(通道值);
返回partialTriple;
}));
var rgbObjects=rgbTriples。选择(
triple=>新RGB(triple[0],triple[1],triple[2]);
通常,使用Zip作为基础组合器可以避免输入长度变化的问题。就其价值而言,我喜欢LINQ并经常使用它,但有时老式的方法是最好的。请注意以下示例:
const int Max = 100000;
var rnd = new Random();
var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
DateTime start;
start = DateTime.Now;
var r1 = list1.Zip(list2, (a, b) => new { a, b }).ToList();
var time1 = DateTime.Now - start;
start = DateTime.Now;
var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i]}).ToList();
var time2 = DateTime.Now - start;
start = DateTime.Now;
var r3 = new int[0].Select(i => new { a = 0, b = 0 }).ToList();
// Easy out-of-bounds prevention not offered in solution #2 (if list2 has fewer items)
int max = Math.Max(list1.Count, list2.Count);
for (int i = 0; i < max; i++)
r3.Add(new { a = list1[i], b = list2[i] });
var time3 = DateTime.Now - start;
Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
Debug.WriteLine("time1 {0}", time1);
Debug.WriteLine("time2 {0}", time2);
Debug.WriteLine("time3 {0}", time3);
const int Max=100000;
var rnd=新随机数();
var list1=Enumerable.Range(1,Max).Select(r=>rnd.Next(Max)).ToList();
var list2=Enumerable.Range(1,Max).Select(r=>rnd.Next(Max)).ToList();
日期时间开始;
start=DateTime.Now;
var r1=list1.Zip(list2,(a,b)=>new{a,b}).ToList();
var time1=DateTime.Now-start;
start=DateTime.Now;
var r2=list1.Select((l1,i)=>new{a=l1,b=list2[i]});
var time2=DateTime.Now-start;
start=DateTime.Now;
var r3=newint[0]。选择(i=>new{a=0,b=0})。ToList();
//解决方案#2中未提供简单的越界预防(如果列表2中的项目较少)
int max=Math.max(list1.Count,list2.Count);
对于(int i=0;i
输出为:
r1==r2:Truer1==r3:True
时间1 00:00:00.0100071
时间2 00:00:00.0170138
时间3 00:00:00.0040028
当然,在这种情况下,时间几乎不值得注意(对人类的感知),因此它可以归结为偏好,但知道#3是最快的,我倾向于在关键性能领域使用它,在这些领域中,类型更复杂,或者枚举数可能更大 另外,请注意使用3时的区别:
const int Max = 100000;
var rnd = new Random();
var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list3 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
DateTime start;
start = DateTime.Now;
var r1 = list1.Zip(list2, (a, b) => new { a, b }).Zip(list3, (ab, c) => new { ab.a, ab.b, c }).ToList();
var time1 = DateTime.Now - start;
start = DateTime.Now;
var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i], c = list3[i] }).ToList();
var time2 = DateTime.Now - start;
start = DateTime.Now;
var r3 = new int[0].Select(i => new { a = 0, b = 0, c = 0 }).ToList();
// Easy out-of-bounds prevention not offered in solution #2 (if list2 or list3 have fewer items)
int max = new int[] { list1.Count, list2.Count, list3.Count }.Max();
for (int i = 0; i < max; i++)
r3.Add(new { a = list1[i], b = list2[i], c = list3[i] });
var time3 = DateTime.Now - start;
Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
Debug.WriteLine("time1 {0}", time1);
Debug.WriteLine("time2 {0}", time2);
Debug.WriteLine("time3 {0}", time3);
const int Max=100000;
var rnd=新随机数();
var list1=Enumerable.Range(1,Max).Select(r=>rnd.Next(Max)).ToList();
var list2=Enumerable.Range(1,Max).Select(r=>rnd.Next(Max)).ToList();
var list3=Enumerable.Range(1,Max).Select(r=>rnd.Next(Max)).ToList();
日期时间开始;
start=DateTime.Now;
var r1=list1.Zip(list2,(a,b)=>new{a,b}).Zip(list3,(ab,c)=>new{ab.a,ab.b,c}).ToList();
var time1=DateTime.Now-start;
start=DateTime.Now;
var r2=list1.Select((l1,i)=>new{a=l1,b=list2[i],c=list3[i]});
var time2=DateTime.Now-start;
start=DateTime.Now;
var r3=newint[0]。选择(i=>new{a=0,b=0,c=0});
//轻松的
const int Max = 100000;
var rnd = new Random();
var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
DateTime start;
start = DateTime.Now;
var r1 = list1.Zip(list2, (a, b) => new { a, b }).ToList();
var time1 = DateTime.Now - start;
start = DateTime.Now;
var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i]}).ToList();
var time2 = DateTime.Now - start;
start = DateTime.Now;
var r3 = new int[0].Select(i => new { a = 0, b = 0 }).ToList();
// Easy out-of-bounds prevention not offered in solution #2 (if list2 has fewer items)
int max = Math.Max(list1.Count, list2.Count);
for (int i = 0; i < max; i++)
r3.Add(new { a = list1[i], b = list2[i] });
var time3 = DateTime.Now - start;
Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
Debug.WriteLine("time1 {0}", time1);
Debug.WriteLine("time2 {0}", time2);
Debug.WriteLine("time3 {0}", time3);
const int Max = 100000;
var rnd = new Random();
var list1 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list2 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
var list3 = Enumerable.Range(1, Max).Select(r => rnd.Next(Max)).ToList();
DateTime start;
start = DateTime.Now;
var r1 = list1.Zip(list2, (a, b) => new { a, b }).Zip(list3, (ab, c) => new { ab.a, ab.b, c }).ToList();
var time1 = DateTime.Now - start;
start = DateTime.Now;
var r2 = list1.Select((l1, i) => new { a = l1, b = list2[i], c = list3[i] }).ToList();
var time2 = DateTime.Now - start;
start = DateTime.Now;
var r3 = new int[0].Select(i => new { a = 0, b = 0, c = 0 }).ToList();
// Easy out-of-bounds prevention not offered in solution #2 (if list2 or list3 have fewer items)
int max = new int[] { list1.Count, list2.Count, list3.Count }.Max();
for (int i = 0; i < max; i++)
r3.Add(new { a = list1[i], b = list2[i], c = list3[i] });
var time3 = DateTime.Now - start;
Debug.WriteLine("r1 == r2: {0}", r1.SequenceEqual(r2));
Debug.WriteLine("r1 == r3: {0}", r1.SequenceEqual(r3));
Debug.WriteLine("time1 {0}", time1);
Debug.WriteLine("time2 {0}", time2);
Debug.WriteLine("time3 {0}", time3);
static class EnumerableExtensions {
public static IEnumerable<TResult> Zip<TSource, TResult>(
this IEnumerable<IEnumerable<TSource>> source,
Func<IEnumerable<TSource>, TResult> resultSelector
) {
if (source == null)
throw new ArgumentNullException("source");
if (resultSelector == null)
throw new ArgumentNullException("resultSelector");
var enumerators = new List<IEnumerator<TSource>>();
try {
foreach (var enumerable in source) {
if (enumerable == null)
throw new ArgumentNullException();
enumerators.Add(enumerable.GetEnumerator());
}
while (enumerators.Aggregate(true, (moveNext, enumerator) => moveNext && enumerator.MoveNext()))
yield return resultSelector(enumerators.Select(enumerator => enumerator.Current));
}
finally {
foreach (var enumerator in enumerators)
enumerator.Dispose();
}
}
}
var reds = new[] { 0x00, 0x03, 0x06, 0x08, 0x09 };
var greens = new[] { 0x00, 0x05, 0x06, 0x07, 0x0a };
var blues = new[] { 0x00, 0x02, 0x03, 0x05, 0x09 };
var colors = new[] { reds, greens, blues }
.Zip(rgb => new RGB(rgb.First(), rgb.Skip(1).First(), rgb.Skip(2).First()));
public static IEnumerable<TResult> Zip<T, TResult>(this IEnumerable<T>[] sequences, Func<T[], TResult> resultSelector)
{
var enumerators = sequences.Select(s => s.GetEnumerator()).ToArray();
while(enumerators.All(e => e.MoveNext()))
yield return resultSelector(enumerators.Select(e => e.Current).ToArray());
}
List_A.Select(a => a.List_B).SelectMany(s => s).ToList();