如何在C#Zip中组合两个以上的通用列表?
我有三个(可能有超过3-4个通用列表,但在这个例子中让3个)通用列表。
List list1 List list2 List list3
所有列表都具有相同数量的元素(相同的计数)。
我用它来组合两个ZIP列表:
var result = list1.Zip(list2, (a, b) => new { test1 = f, test2 = b }
我用它foreach
语句,以避免foreach
每个List,就像
foreach(var item in result){ Console.WriteLine(item.test1 + " " + item.test2); }
如何在三个列表中使用带有Zip的simmilary?
谢谢
编辑:
我想要:
List list1 = new List{"test", "otherTest"}; List list2 = new List{"item", "otherItem"}; List list3 = new List{"value", "otherValue"};
ZIP之后(我不知道方法),我想结果(在VS2010调试模式下)
[0] { a = {"test"}, b = {"item"}, c = {"value"} } [1] { a = {"otherTest"}, b = {"otherItem"}, c = {"otherValue"} }
怎么做 ?
对我来说最明显的方法是使用Zip
两次。
例如,
var results = l1.Zip(l2, (x, y) => x + y).Zip(l3, (x, y) => x + y);
将组合(添加)三个List
对象的元素。
更新:
您可以定义一个新的扩展方法,其行为类似于具有三个IEnumerable
的Zip
,如下所示:
public static class MyFunkyExtensions { public static IEnumerable ZipThree( this IEnumerable source, IEnumerable second, IEnumerable third, Func func) { using (var e1 = source.GetEnumerator()) using (var e2 = second.GetEnumerator()) using (var e3 = third.GetEnumerator()) { while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) yield return func(e1.Current, e2.Current, e3.Current); } } }
用法(与上述相同)现在变为:
var results = l1.ZipThree(l2, l3, (x, y, z) => x + y + z);
同样,您现在可以将三个列表组合使用:
var results = list1.ZipThree(list2, list3, (a, b, c) => new { a, b, c });
您可以将C#中的许多列表与级联zip方法和匿名类以及Tuple结果组合在一起。
List list1 = new List { "test", "otherTest" }; List list2 = new List { "item", "otherItem" }; List list3 = new List { "value", "otherValue" }; IEnumerable> result = list1 .Zip(list2, (e1, e2) => new {e1, e2}) .Zip(list3, (z1, e3) => Tuple.Create(z1.e1, z1.e2, e3));
结果是:
[0] {(test, item, value)} Item1: "test" Item2: "item" Item3: "value"
class Program { static void Main(string[] args) { List list1 = new List { "test", "otherTest" }; List list2 = new List { "item", "otherItem" }; List list3 = new List { "value", "otherValue" }; var result = CombineListsByLayers(list1, list2, list3); } public static List [] CombineListsByLayers(params List [] sourceLists) { var results = new List [sourceLists[0].Count]; for (var i = 0; i < results.Length; i++) { results[i] = new List (); foreach (var sourceList in sourceLists) results[i].Add(sourceList[i]); } return results; }
我知道另一个非常有趣的解决方案。 它主要是从教育角度来看很有趣,但是如果需要执行压缩不同的列表计数A LOT,那么它也可能是有用的。
此方法重写.NET的LINQ SelectMany
函数,当您使用LINQ的查询语法时,该函数由约定使用。 标准的SelectMany
实现执行笛卡尔积。 被覆盖的人可以做拉链。 实际的实施可能是:
static IEnumerable SelectMany(this IEnumerable source, Func> selector, Func select) { using (var e1 = source.GetEnumerator()) using (var e2 = selector(default(TSource)).GetEnumerator()) while (true) if (e1.MoveNext() && e2.MoveNext()) yield return select(e1.Current, e2.Current); else yield break; }
它看起来有点可怕,但它是一个压缩的逻辑,如果写一次,可以在很多地方使用,客户端的代码看起来很不错 – 你可以使用标准的LINQ查询语法压缩任意数量的IEnumerable
:
var titles = new string[] { "Analyst", "Consultant", "Supervisor"}; var names = new string[] { "Adam", "Eve", "Michelle" }; var surnames = new string[] { "First", "Second", "Third" }; var results = from title in titles from name in names from surname in surnames select $"{ title } { name } { surname }";
如果你然后执行:
foreach (var result in results) Console.WriteLine(result);
你会得到:
Analyst Adam First Consultant Eve Second Supervisor Michelle Third
您应该将此扩展保持在您的类中,因为否则您将从根本上改变周围代码的行为。 此外,新类型将非常有用,因此它不会与IEnumerables的标准LINQ行为相符。
出于教育目的,我使用此扩展方法创建了一个小型c#项目+几个好处: https : //github.com/lukiasz/Zippable
此外,如果您觉得这很有趣,我强烈推荐Jon Skeet重新实现LINQ to Objects文章 。
玩得开心!
- 在C#中解析具有Html敏捷性的表格,单元格
- IsTabStop =“False”对我的WPF应用程序没有影响
- DateTime.Now和Culture / Timezone特定
- DllImport返回null终止字符串AccessViolationException
- 如何在Entity Framework 4中的LINQ表达式中执行Oracle函数?
- 无法加载Windows.winmd
- Microsoft.Http.HttpClient,在重定向上正确发送HTTP身份validation参数
- 从Entity Framework 4.1 Code First中的NotMapped类派生实体类
- 只有在创建Window并显示为对话框后才能设置DialogResult