Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 按键分组顺序列表_C#_Linq - Fatal编程技术网

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