我有一个由较小列表的集合组成的列表。我需要根据特定值将聚合列表拆分为较小的列表。
我尝试使用.Take()方法,但是它使用一个整数,我不一定知道较小的列表将要持续多长时间。
我的列表大列表看起来像这样
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);
我需要能够根据“ LineTypeB”将“ Bar”拆分为较小的列表。因此,一个列表将包含3个元素,而另一个列表将包含以上示例中的两个元素。在该线程中有一个类似的解决方案可以执行我想做的事,但在python中-Python splitting a list based on a delimiter word
答案 0 :(得分:0)
让我们假设您具有列表中将包含的类型:
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);
接下来,您可以使用LINQ来制作一个平面列表(如果您只有一个内部列表(例如,只有Foo1),甚至可能不需要):
List<MyItem> flatList = Bar.SelectMany(innerList => innerList).ToList();
string expectedValue = "LineTypeB";
现在到最重要的部分,您可以通过为列表创建扩展方法来做到这一点:
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;
}
}
然后您像在flatList上一样调用它:
var splitList = flatList.SplitListByValue(expectedValue);
我希望这会有所帮助。
答案 1 :(得分:0)
这是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;
}
然后,您可以将其用于这样的示例。
var results = Bar.SelectMany(x => x).SplitOn(x => x.Value == "LineTypeB");