LINQ方法通过函数连接一系列中的每个n个元素,然后将这些结果重新聚合到一个新列表中?

不确定这个问题的标题是否清楚,但是这里有。 我的ASP.NET MVC 3应用程序中有一些相当混乱的代码,当打印出来时,将每2个(但可以从1-n配置)项目包装在div标签的列表中。 我想像这样创建一个LINQ函数:

// Can't think of a better name IEnumerable FormattedSubsetList(IEnumerable items, int every = 2, [delegate to a method to join the N elements]) { } 

对不起,如果这有点复杂…我会试一个例子。 假设我有一个Widget列表。 我想打印出我所有小部件的名称(假设我有7个),我希望每2个小部件都在div中。 所以如果我有……

 var list = new List(); list.Add(new Widget() { Name = "One" }); //... you get the picture list.Add(new Widget() { Name = "Seven" }); IEnumerable newList = FormattedSubsetList(list, 2, (one, two) => (return "
" + string.Join(" ", one.Name, two.Name) + "
"); string finalString = string.Join(string.Empty, newList); // finalString ==
One Two
Three Four
Five Six
Seven

如果有什么不清楚我会道歉但我根本不知道这是什么类型的东西,并且不知道如何实施它。 我知道我的LINQ语法在某些地方也有点偏差。

这里有两种扩展方法可以完全满足您的需求。 Split方法是可重用的,它只是将任何IEnumerable拆分为一个枚举列表,因此每个subenumerable都不超过size元素。 第二种方法ToFormattedList是执行您要求的客户方法。

 public static class Extenstions { public static IEnumerable ToFormattedList( this IEnumerable source, int count, Func, TRestul> formatter) { return source.Split(count).Select(arg => formatter(arg.ToList())); } public static IEnumerable> Split(this IEnumerable source, int size) { var i = 0; return from element in source group element by i++ / size into splitGroups select splitGroups.AsEnumerable(); } } 

如何使用:

 var list = new List { new Widget { Name = "One" }, new Widget { Name = "Two" }, new Widget { Name = "Three" }, new Widget { Name = "Four" }, new Widget { Name = "Five" }, new Widget { Name = "Six" }, new Widget { Name = "Seven" }, new Widget { Name = "Eight" } }; var newList = list.ToFormattedList(2, args => "
" + args[0].Name + args[1].Name + "
"); var finalString = string.Join(string.Empty, newList); // finalString =
OneTwo
ThreeFour
FiveSix
SevenEight

但是,如果列表具有奇数个元素,则会出现问题,因为args [1]将在最后一个元素上抛出exception。 所以你可以这样做:

 var newList = list.ToFormattedList(2, args => "
" + string.Join(" ", args.Select(arg => arg.Name)) + "/
");

您可以在简单的选择呼叫中实现分组。 这是一个小型控制台应用程序,可以满足您的需求:

 var list = new List(); for (int i = 0; i < 7; i++) list.Add("Widget #" + (i + 1)); var groupedWidgets = list .Select((w, i) => new { Widget = w, Index = i }) .GroupBy(x => (int)(x.Index / 2)); foreach (var g in groupedWidgets) { Console.WriteLine("
"); foreach (var w in g) { Console.WriteLine(" " + w.Widget); } Console.WriteLine("
"); }

因此我将“Index / 2”分组为int,这意味着第1项和第2项将一起结束,然后第3项和第4项等。将“2”更改为“3”将小部件组合在一起。

那有意义吗?

更新这是一个返回分组元素列表的通用函数:

 public static class Extensions { public static IEnumerable> GroupSelect(this IEnumerable list, int groupSize) { return list .Select((t, i) => new { t, i }) .GroupBy(x => (int)(xi / groupSize), x => xt); } } 

所以现在你可以写:

 foreach (var g in list.GroupSelect(3)) { Console.WriteLine("
"); foreach (var w in g) { Console.WriteLine(" " + w); } Console.WriteLine("
"); }

这是一种应该满足您需求的扩展方法。

  public static IEnumerable FormatSubsetList(this IEnumerable input, int every, Func,string> formatter) { List list = new List (); int index = 0; foreach (T i in input) { T[] array; if (index % every == 0) list.Add (array = new T[every]); else array = list[list.Count - 1]; array[index++ % every] = i; } return list.Select(t => t.Where (i => i != null)).Select(formatter); } static Program() { List widgets = new List (); Func,string> formatter = items => items.Aggregate (new StringBuilder ("
"), (sb,w) => sb.Append(" ").Append (w.Name), sb => sb.Append ("
").ToString ()); widgets.FormattedSubsetList(3, formatter); }