Linq 如何基于模式按T的顺序划分IEnumerable(Of T)?
考虑以下IEnumerable(字符串的): 它们在视觉上是分开的,以使图案更容易看到。我想使用.StartsWith()谓词将IEnumerable(Of String)划分为IEnumerable(Of IEnumerable)(Of String) 这些规则是:Linq 如何基于模式按T的顺序划分IEnumerable(Of T)?,linq,ienumerable,subset,Linq,Ienumerable,Subset,考虑以下IEnumerable(字符串的): 它们在视觉上是分开的,以使图案更容易看到。我想使用.StartsWith()谓词将IEnumerable(Of String)划分为IEnumerable(Of IEnumerable)(Of String) 这些规则是: 每个分区子集都必须有一个Larry,并且可能有一个Moe 遇到Moe时Moe上的分区 如果拉里紧跟着莫伊,把他放在最后一个莫伊 如果Larry立即跟随其他人,则在Larry 所有其他工具都与当前分区放在一起 除了Moe和Larr
- 每个分区子集都必须有一个Larry,并且可能有一个Moe
- 遇到Moe时Moe上的分区
- 如果拉里紧跟着莫伊,把他放在最后一个莫伊
- 如果Larry立即跟随其他人,则在Larry
- 所有其他工具都与当前分区放在一起
- 除了Moe和Larry之外的所有stooge都可以在分区中重复
提前感谢。LINQ在这里似乎不是一个解决方案,因为您有非常复杂的拆分条件,并且您想要生成的数据结构不是LINQ查询的典型数据结构。好的,唯一一个打算一次知道序列中多个元素的LINQ操作符是
聚合
,但它不适合这里,因为我们已经讨论过了与聚合相反的操作
因此,使用经典循环似乎可以更轻松地解决您的问题,而不是像这样(未经过彻底测试):
公共IEnumerable分区(IEnumerable输入)
{
var currPartition=新列表();
字符串prev=null;
foreach(输入中的变量元素)
{
if(应划分(上一部分,要素))
{
收益率分割;
currPartition=新列表();
}
添加(elem);
prev=elem;
}
收益率分割;
}
私有bool ShouldPartition(字符串前置,字符串元素)
{
if(prev==null)
返回false;
如果(要素开始与(“Moe”))
返回true;
如果(要素开始与(“拉里”))
return!上一个StartsWith(“Moe”);
返回false;
}
这看起来像一个小型状态机,使用标准for循环和手动创建单个子集合可能要容易得多-在我看来,Linq不会让这变得更容易。非常感谢这个干净的示例-我认为这是我最终要走的路线。
Moe1
Larry1
Curly1
Shemp1
Curly1
Moe2
Larry1
Curly1
Shemp1
Curly1
Curly2
Shemp2
Curly1
Curly2
Larry2
Curly1
Larry3
Shemp1
public IEnumerable<IEnumerable<string>> Partition(IEnumerable<string> input)
{
var currPartition = new List<string>();
string prev = null;
foreach (var elem in input)
{
if (ShouldPartition(prev, elem))
{
yield return currPartition;
currPartition = new List<string>();
}
currPartition.Add(elem);
prev = elem;
}
yield return currPartition;
}
private bool ShouldPartition(string prev, string elem)
{
if (prev == null)
return false;
if (elem.StartsWith("Moe"))
return true;
if (elem.StartsWith("Larry"))
return !prev.StartsWith("Moe");
return false;
}