是否存在“;分割列表”;方法
本文关键字:方法 列表 分割 是否 存在 | 更新日期: 2023-09-27 18:23:47
在C#中,调用.Split
方法会将字符串拆分为基于某个字符或字符串的字符串数组。
对于列表或数组,是否有等效的方法?
例如:
var foo = new List<int>() { 1, 2, 3, 0, 4, 5, 0, 6 };
var output = Split(foo, 0);
// produces { { 1, 2, 3 }, { 4, 5 }, { 6 } }
这就是我到目前为止所拥有的——有没有一种更干净或更雄辩的方式来完成同样的任务?
IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> list, T divider)
{
var output = new List<List<T>>();
var temp = new List<T>();
foreach ( var item in list )
{
if (item.Equals(divider))
{
output.Add(temp);
temp = new List<T>();
}
else
{
temp.Add(item);
}
}
output.Add(temp);
return output;
}
编辑:
我突然想到,我的版本只会用一个元素来分割列表,而string.Split
可以用一个字符或任意字符串来分割。
为了完整起见,实现这一点的最佳方式是什么?
没有内置的等价物,但延迟评估的是
IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> list, T divider)
{
var temp = new List<T>();
foreach (var item in list)
{
if (!item.Equals(divider))
{
temp.Add(item);
}
else
{
yield return temp;
temp = new List<T>();
}
}
if(temp.Count>0) yield return temp;
}
不,框架中没有专门的现有方法来分割序列。
你的代码是合理的。
改进/改变的途径:
- 您可以使用
yield return
而不是添加到output
来获得一些惰性评估 - 使用更有趣的代码,您也可以使内部列表变得懒惰(如果传入序列没有绑定/段太长,这可能很重要)
- 如果你想展示单语句代码,你可以使用
Aggregate
不知道任何内置函数。然而,我会考虑这样做:
public static IEnumerable<List<int>> Split(List<int> list, int delimiter)
{
var start = 0;
foreach (var end in list.FindAll(x => x == delimiter).Select(splitter => list.IndexOf(splitter, start)))
{
yield return list.GetRange(start, end - start);
start = end + 1;
}
if (start <= list.Count)
{
yield return list.GetRange(start, list.Count - start);
}
}