Linq 如何基于模式按T的顺序划分IEnumerable(Of T)?

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

考虑以下IEnumerable(字符串的):

它们在视觉上是分开的,以使图案更容易看到。我想使用.StartsWith()谓词将IEnumerable(Of String)划分为IEnumerable(Of IEnumerable)(Of String)

这些规则是:

  • 每个分区子集都必须有一个Larry,并且可能有一个Moe
  • 遇到MoeMoe上的分区
  • 如果拉里紧跟着莫伊,把他放在最后一个莫伊
  • 如果Larry立即跟随其他人,则在Larry
  • 所有其他工具都与当前分区放在一起
  • 除了MoeLarry之外的所有stooge都可以在分区中重复
我使用的是.StartsWith(“Moe”),等等,以确定stooge的类型,但我很难弄清楚如何使用LINQ运算符对该集进行分区,因此如果存在Moe,他表示分区的头,但是由于Larry必须存在于每个分区中,如果Moe不存在,他可能表示分区的头在他前面

如何创建IEnumerable(Of IEnumerable(Of String))以使结果按我用空行显示集的方式进行分区

如果没有适合这样的LINQ操作符(如果VB.NET和C#之间的功能存在细微差异,我将在VB.NET中编程),并且我只需要编写一个方法来实现这一点,我就可以做到,但我认为这可能是一个问题,可以通过LINQ操作符轻松解决


提前感谢。

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;
}