C# 基于分隔符从现有列表创建较小的列表
我有一个列表,它由一系列较小的列表组成。我需要根据特定值将聚合列表拆分为更小的列表 我曾尝试使用.Take方法,但这需要一个整数,我不一定知道较小的列表将有多长 我的列表大列表看起来像这样C# 基于分隔符从现有列表创建较小的列表,c#,list,xamarin,nested-lists,C#,List,Xamarin,Nested Lists,我有一个列表,它由一系列较小的列表组成。我需要根据特定值将聚合列表拆分为更小的列表 我曾尝试使用.Take方法,但这需要一个整数,我不一定知道较小的列表将有多长 我的列表大列表看起来像这样 List<T> Foo = new List<T>(); Foo.Add("Test1", "LineTypeA"); Foo.Add("Test2", "LineTypeA"); Foo.Add("Test3", "LineTypeB"); Foo.Add("Test4", "Lin
List<T> Foo = new List<T>();
Foo.Add("Test1", "LineTypeA");
Foo.Add("Test2", "LineTypeA");
Foo.Add("Test3", "LineTypeB");
Foo.Add("Test4", "LineTypeA");
Foo.Add("Test5", "LineTypeB");
List<List<T> Bar = new List<ListT>>();
Bar.Add(Foo);
我需要能够分割成更小的列表栏基于线型B。因此,一个列表将包含3个元素,另一个列表将包含上面示例中的两个元素。在这个线程中有一个类似的解决方案来完成我想要的任务,但在python中-让我们假设您有您的类型,您的列表将包含:
public class MyItem
{
public string Key { get; set; }
public string Value { get; set; }
public MyItem(string key, string value)
{
Key = key;
Value = value;
}
}
您创建的初始列表如下所示:
List<MyItem> Foo1 = new List<MyItem>();
Foo1.Add(new MyItem("Test1", "LineTypeA"));
Foo1.Add(new MyItem("Test2", "LineTypeA"));
Foo1.Add(new MyItem("Test3", "LineTypeB"));
Foo1.Add(new MyItem("Test4", "LineTypeA"));
Foo1.Add(new MyItem("Test5", "LineTypeB"));
List<MyItem> Foo2 = new List<MyItem>();
Foo2.Add(new MyItem("Test1", "LineTypeA"));
Foo2.Add(new MyItem("Test2", "LineTypeA"));
Foo2.Add(new MyItem("Test3", "LineTypeB"));
Foo2.Add(new MyItem("Test4", "LineTypeA"));
Foo2.Add(new MyItem("Test5", "LineTypeB"));
List<MyItem> Foo3 = new List<MyItem>();
Foo3.Add(new MyItem("Test1", "LineTypeA"));
Foo3.Add(new MyItem("Test2", "LineTypeA"));
Foo3.Add(new MyItem("Test3", "LineTypeB"));
Foo3.Add(new MyItem("Test4", "LineTypeA"));
Foo3.Add(new MyItem("Test5", "LineTypeB"));
List<List<MyItem>> Bar = new List<List<MyItem>> ();
Bar.Add(Foo1);
Bar.Add(Foo2);
Bar.Add(Foo3);
我希望这会有所帮助。这里是与Python问题中的答案相当的C语言。我将其更改为不接受分隔符,而是接受一个确定该项是否为分隔符的委托。我还修复了当集合为空或第一项匹配时不返回空集合的问题
public static IEnumerable<IEnumerable<T>> SplitOn<T>(
this IEnumerable<T> items,
Func<T, bool> split)
{
var g = new List<T>();
foreach(var item in items)
{
if(split(item) && g.Count > 0)
{
yield return g;
g = new List<T>();
}
g.Add(item);
}
if(g.Count > 0) yield return g;
}
不清楚你的数据是什么样子的。Foo是一个列表,其中每个子列表都有两个值,还是Foo是一个列表,其中SomeType是两个字符串的组合,您打算执行类似Foo.Addnew SomeTypeTest1,LineTypeA;?抱歉没有更彻底。Foo是某种类型的列表。然后,我需要Bar在Foo中循环并向列表中添加值,直到找到某个值为止。在上面的示例中,条形图将循环通过Foo并将值添加到列表中,直到到达包含LineTypeB的条目,然后是由剩余值组成的第二个列表,直到最终的LineTypeB。您的答案在不同列表中的布局是正确的@zpouip,但这不是我希望创建这些新列表的方式在一定的价值上。在上面的示例中,我需要循环遍历列表,直到找到LineTypeB,然后将该值及其之前的所有内容添加到新列表中。这个过程会一直重复,直到我剩下类似List1=Test1、LineTypeA、Test2、LineTypeA、Test3、LineTypeB和List2=Test4、LineTypeA、Test5、LineTypeB的内容。格式化很糟糕,因为我在手机上。希望这能澄清一点。啊,好吧,现在更清楚了,我会相应地更新我的答案。@Kizzle我更新了我的答案。请注意,在我的扩展方法中,当我找到具有预期值的元素时,我会立即剪切它并创建新的子列表。我不确定你是否想这样做。如果不是这样的话,你只需要更新else If语句,也许你可以在里面切换两行的顺序。你是个天才@zpouip你可以用Last代替LastOrDefault,因为你知道主列表总是至少有一个子列表。
public static class ListExtensionMethods
{
public static List<List<MyItem>> SplitListByValue(this List<MyItem> list, string value)
{
List<List<MyItem>> splittedList = new List<List<MyItem>>() { new List<MyItem>() }; // initial set
for (int i = 0; i < list.Count; i++)
{
var currentItem = list[i];
if (i == 0 && currentItem.Value == value) //if the first element already meets the condition, add it to the first sublist and create new one
{
splittedList.LastOrDefault().Add(currentItem);
splittedList.Add(new List<MyItem>());
}
else if (currentItem.Value == value)
{
splittedList.Add(new List<MyItem>()); //if i-th element meets the condition, create new sublist and add it there
splittedList.LastOrDefault().Add(currentItem);
}
else
{
splittedList.LastOrDefault().Add(currentItem);
}
}
return splittedList;
}
}
var splitList = flatList.SplitListByValue(expectedValue);
public static IEnumerable<IEnumerable<T>> SplitOn<T>(
this IEnumerable<T> items,
Func<T, bool> split)
{
var g = new List<T>();
foreach(var item in items)
{
if(split(item) && g.Count > 0)
{
yield return g;
g = new List<T>();
}
g.Add(item);
}
if(g.Count > 0) yield return g;
}
var results = Bar.SelectMany(x => x).SplitOn(x => x.Value == "LineTypeB");