【问题标题】:Unique List, but keep blank lines唯一列表,但保留空行
【发布时间】:2023-04-10 04:14:01
【问题描述】:

我正在寻找一种使用 linq 制作唯一列表的方法

原始列表

Level 01
Level 01
-- Blank Line --
Level 02
Level 02
-- Blank Line --
Level 03
Level 03
-- Blank Line --
Level 04
Level 04

等等

我想做什么:

Level 01
-- Blank Line --
Level 02
-- Blank Line --
Level 03
-- Blank Line --
Level 04

谢谢

【问题讨论】:

  • 请改进您问题的格式。以目前的格式阅读起来非常困难。见stackoverflow.com/editing-help
  • 如果将行格式化为代码,它不会将换行符换行。
  • 是否有可能在列表后面的“Level 02”行之后的某个地方有一个“Level 01”行?还是保证在任何给定的空行之后,该空行之前的任何非空行都不会重复?
  • 是的,我无法格式化帖子,感谢您格式化我的帖子和链接

标签: c# list linq


【解决方案1】:

你可以使用Enumerable.Aggregate:

string blankLine = // whatever a blank line is

var list = new List<string>
{
    "Level 01",
    "Level 01",
    blankLine,
    "Level 02"
    "Level 02"
    blankLine,
    // ...
};

var unique = list
    .Aggregate(
        Enumerable.Empty<string>(), // Initial accumulator value
        (acc, x) => x == blankLine || !acc.Contains(x) ? acc.Append(x) : acc); 

【讨论】:

  • 这里不符合要求。
  • 我的错;初始值在累加器函数之前。
  • 它仍然告诉我 'IEnumerable 不包含 Append 接受 'IEnumerable 的第一个参数的定义..
  • 什么版本的.Net?它仅在 .Net Framework 4.7.1 中引入。
  • 啊,VS2017 (.NET 4.6.1) 抱怨,VS2019 (.NET 4.7.2) 没有。而且效果很好..
【解决方案2】:

您的规范不完整。你想用这个输入做什么:

Level 01
Level 02
-- Blank Line --
Level 03
Level 04
-- Blank Line --

那么两个连续的空行呢?

Level 01
Level 01
-- Blank Line --
-- Blank Line --
Level 02

如果你的输入序列是空的,你想要什么?一个空的输出,还是只有一个空行?

假设你没有这个。你的要求是:

给定一个字符串的输入序列,没有两个连续的空行。取第一个字符串,跳过所有字符串,直到第一个空字符串。取空​​字符串。重复此操作直到序列结束。

所以你取第一个“Level 01”,跳过所有行,直到空行,你取空行,然后是第一行:“Level 02”。跳过所有行直到下一个空行,取下一个空行,等等。

可能“空字符串”实际上是“-- 空白行--”。我假设您足够聪明,可以相应地更改代码。

您可以在一个大的 LINQ 语句中做到这一点。我认为如果您制作扩展方法,您的代码将更容易阅读、理解、重用、测试和维护。如果你不熟悉扩展方法,请参阅extension methods demystified

static IEnumerable<string> SkipContiguousLines(this IEnumerable<string> source)
{
    // TODO implement
}

我们先看看界面是否如你所愿:

IEnumerable<string> lines = ... // get the input
IEnumerable<string> remainingLines = lines.SkipContiguous();

或者在更大的 LINQ 中:

var result = orderLines.GroupBy(orderLine => orderLine.OrderId)
                       .Select(group => new
                       {
                           OrderId = group.Key,
                           OrderLines = group.SkipContiguous(),
                       });

代码相当简单:

static IEnumerable<string> SkipContiguousLines(this IEnumerable<string> lines)
{
    string blankLine = String.Empty;   // or ----- Blank Line ---- ?

    using (var lineIterator in lines.GetEnumerator())
    {
        bool lineAvailable = lineIterator.MoveNext();
        while (lineAvailable)
        {
            // there is still something in your input:
            yield return lineIterator.Current;

            // skip until blank line:
            while (lineAvailable && lineIterator.Current != blankLine)
            {
                 lineAvailable = lineIterator.MoveNext();
            }

            // if not at end, you found a blank line: return the blank line
            if (lineAvailable) yield return blankLine;
        }
    }
}

【讨论】:

  • 你猜对了,我很聪明,只是我是初学者,所以我还在学习。谢谢
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 2021-06-23
  • 1970-01-01
  • 2018-07-31
  • 2018-11-21
  • 2011-07-12
  • 1970-01-01
  • 2020-04-15
相关资源
最近更新 更多