如何根据 T 的顺序模式对 IEnumerable(Of T) 进行分区?

发布于 2024-11-29 05:59:02 字数 1226 浏览 0 评论 0原文

考虑以下 IEnumerable(Of String):

    Moe1
    Larry1
    Curly1
    Shemp1
    Curly1

    Moe2
    Larry1
    Curly1
    Shemp1
    Curly1
    Curly2
    Shemp2
    Curly1
    Curly2

    Larry2
    Curly1

    Larry3
    Shemp1

它们在此处在视觉上分开,以使模式更易于查看。我想使用 .StartsWith() 谓词将 IEnumerable(Of String) 分区为 IEnumerable(Of IEnumerable(Of String)。

规则是:

  • 每个分区子集必须有一个 Larry 可能Moe上有一个Moe
  • ,并且当Moe遇到时,
  • 如果Larry立即跟随, 分区Moe,将他与最后一个Moe放在一起,
  • 如果Larry立即跟随其他任何人,
  • 则将所有其他傀儡 放在当前分区
  • 分配给Larry将除MoeLarry 之外的所有傀儡

中都可以在分区中重复我正在使用 .StartsWith("Moe") 等来识别类型跟屁虫,但我有很难弄清楚如何使用 LINQ 运算符对这个集合进行分区,以便 如果 Moe 存在,他代表分区的头,但由于 Larry强>必须存在于每个分区中,如果Moe不在他之前,他可能代表分区的头。

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

如果没有合适的 LINQ 运算符来实现类似的操作(我正在 VB.NET 中编程,如果VB.NET 和 C# 之间的功能存在细微差别,我只需要编写一个方法来执行此操作,我可以做到这一点,但我认为这可能是一个出现的问题,并且可以通过 LINQ 轻松解决。 。

预先感谢

Consider the following IEnumerable(Of String):

    Moe1
    Larry1
    Curly1
    Shemp1
    Curly1

    Moe2
    Larry1
    Curly1
    Shemp1
    Curly1
    Curly2
    Shemp2
    Curly1
    Curly2

    Larry2
    Curly1

    Larry3
    Shemp1

They're visually split here to make the pattern easier to see. I want to partition an IEnumerable(Of String) using the .StartsWith() predicate, into an IEnumerable(Of IEnumerable(Of String).

The rules are:

  • every partitioned subset must have a Larry, and might have a Moe
  • partition on Moe when Moe encountered
  • if Larry immediately follows Moe, put him with the last Moe
  • if Larry immediately follows anyone else, partition on Larry
  • all other stooges are put with the current partition
  • all stooges other than Moe and Larry can repeat in a partition

I'm using the .StartsWith("Moe"), etc. to identify the type of stooge, but I'm having a hard time figuring out how to partition this set using LINQ operators so that if Moe is present, he represents the head of a partition, but since Larry must exist in each partition, he might represent the head of a partition if a Moe does not precede him.

How can I create the IEnumerable(Of IEnumerable(Of String) so that the result is partitioned the way I display the set with blank lines?

If there are no suitable LINQ operators for something like this (I'm programming in VB.NET if there are subtle differences in capabilities between VB.NET & C#), and I simply need to write a method to do this, I can do that, but I thought this might be a problem that comes up and is solved easily with LINQ operators.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷乱花海 2024-12-06 05:59:02

LINQ 似乎不是这里的解决方案,因为您有相当复杂的拆分条件,并且您想要生成的数据结构对于 LINQ 查询来说并不典型。 AFAIK,唯一旨在一次了解序列中多个元素的 LINQ 运算符是聚合,但它不适合这里,因为我们正在做与聚合相反的事情。

因此,使用经典循环似乎可以更轻松地解决您的问题,而不是像这样(未经过彻底测试):

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

LINQ doesn't seem to be a solution here as you have pretty complex split condition and the data structure you want to produce is not typical for LINQ queries. AFAIK, the only LINQ operator that is intended to know more than one element of the sequence at once is Aggregate, but it doesn't fit here as we're doing something inverse from aggregating.

So your problem seems to be solved easier using classical loops, more less like that (not tested thoroughly):

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文