C# 按键分组顺序列表
我正在尝试将相关条目的列表分组 我的清单如下:C# 按键分组顺序列表,c#,linq,C#,Linq,我正在尝试将相关条目的列表分组 我的清单如下: new List<string>() { "Entry1", "Metadata1", "Metadata2", "Entry2", "Metadata3", "Metadata4" }; 我希望对条目进行分组,以{Entry1,Metadata1,Metadata2}和{Entry2,Metadata3,Metadata4}作为分组 输入字段之间的项目数不确定。我想使用LINQ来完成这
new List<string>() { "Entry1", "Metadata1", "Metadata2",
"Entry2", "Metadata3", "Metadata4" };
我希望对条目进行分组,以{Entry1,Metadata1,Metadata2}和{Entry2,Metadata3,Metadata4}作为分组
输入字段之间的项目数不确定。我想使用LINQ来完成这项工作
我如何将这些元素组合到由条目元素分隔的集合中?这里有一个想法需要改进,在LINQPad中实现,下面是一个:
这是一个解决方案和输出。希望这就是你想要做的
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<string> datas = new List<string>() { "Entry1", "Metadata1", "Metadata2", "Entry2", "Metadata3", "Metadata4" };
List<List<string>> grouped = new List<List<string>>();
int count = -1;
foreach (string e in datas)
{
if (e.StartsWith("Entry"))
{
grouped.Add(new List<string>());
grouped[++count].Add(e);
}
else
{
grouped[count].Add(e);
}
}
for (int i = 0; i < grouped.Count; i++)
{
for (int j = 0; j < grouped[i].Count; j++)
{
Console.WriteLine(grouped[i][j]);
}
Console.WriteLine();
}
}
}
}
输出如您所愿:
一种可能的解决方案是获取条目的索引,并使用列表的GetRange方法使用索引获取范围内的项:
var indices = yourList
.Where(x => x.StartsWith("Entry"))
.Select(x => yourList.IndexOf(x))
.ToList();
var groups = indices
.Select((x,idx) => idx != indices.Count - 1
? yourList.GetRange(x, indices[idx + 1] - x)
: yourList.GetRange(x, yourList.Count - x))
.ToList();
你要找的是一个iGroup或ILookup。问题是,您必须调用框架方法来生成不适用于此场景的方法,因为如果您在每次迭代中使用字典,则无法同时提取一个键和一个值或一个键和多个值。在这个场景中使用LINQ的问题是,为了得到您想要的东西,您必须在集合上迭代多次,以便正确地对所有内容进行分组。执行您所要求的操作的最有效方法是在for循环中手动检查数据并创建字典,创建DictionaryEntry,并在每次按下新键时添加它们。一种折衷方法是使用ToLookup投影数据,为带有垃圾密钥的密钥添加条目,然后按如下方式进行筛选:
var data = new List<string>() { "Key1", "Value1", "Value2",
"Key2", "Value3", "Value4" };
string workingKey = null;
data.ToLookup(item => {
if(item.StartsWith("Key"))
{
workingKey = item;
return String.Empty; //use whatever here
}
return workingKey;
}).Where(g => g.Key != String.Empty); //make sure to enumerate this if you plan on setting workingKey after this EDIT: Where is enumerating so no need to enumerate again
.Net小提琴演示:
代码:
您是如何看待这一工作的?项目是否总是以3为一组,还是每次列表中有一个以字符串开头的条目时,您都想要一个新对象,后面有所有的项目?@JohnLBevan,后者。每个集合之间的条目数未知。每次看到以条目开头的项目时,它都应该创建一个新列表,其内容是该条目以及下一个条目字段之前的后续项目。这非常有效。“我也喜欢使用收益率,我经常努力在日常生活中为它找到一个位置。”格兰斯。这里有一个很好的使用收益率的例子:这也非常有效!这是一个有趣的方法,有点接近我的大脑想要解决这个问题的方式。我将把这个标记为正确的,因为它稍微更通用一些。分组不关心类型,这很好,并且使它更易于移植。感谢您的解决方案。这是可行的,但我正在寻找一个使用LINQ的解决方案。不管怎么说,你的作品和广告上的一样。
var data = new List<string>() { "Key1", "Value1", "Value2",
"Key2", "Value3", "Value4" };
string workingKey = null;
data.ToLookup(item => {
if(item.StartsWith("Key"))
{
workingKey = item;
return String.Empty; //use whatever here
}
return workingKey;
}).Where(g => g.Key != String.Empty); //make sure to enumerate this if you plan on setting workingKey after this EDIT: Where is enumerating so no need to enumerate again
//create initial list
List<string> myList = new List<string>{"Entry1","a","b","Entry2","c","d","e"};
//remember previous group name
string previousGroupName = null;
//create grouped list
var myGroupedList =
myList.Select(i => new{
Value=i
,GroupName=(i.StartsWith("Entry")?(previousGroupName = i):previousGroupName)
})
.GroupBy(gb => gb.GroupName);
//output to LinqPad (if running there)
myGroupedList.Dump();
Key = Entry1
Value GroupName
Entry1 Entry1
a Entry1
b Entry1
Key = Entry2
Value GroupName
Entry2 Entry2
c Entry2
d Entry2
e Entry2