唯一列表,但保留空行

时间:2021-02-22 16:12:31

标签: c# list linq

我正在寻找一种使用 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

谢谢

2 个答案:

答案 0 :(得分: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); 

答案 1 :(得分:0)

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

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