基于谓词拆分LINQ查询

Ari*_*iac 6 c# linq

我想要一种方法,它会IEnumerable在谓词中拆分,通过相对于谓词的索引将项目组合在一起.例如,它可以分割List<string>满足的项目x => MyRegex.Match(x).Success,其中"中间"项目将这些匹配组合在一起.

它的签名可能看起来像一些线

public static IEnumerable<IEnumerable<TSource>> Split<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate,
    int bool count
)
Run Code Online (Sandbox Code Playgroud)

,可能还有一个包含所有分隔符的输出的额外元素.

有没有比foreach循环更有效和/或更紧凑的方法来实现它?我觉得应该可以用LINQ方法实现,但我不能指责它.

例:

string[] arr = {"One", "Two", "Three", "Nine", "Four", "Seven", "Five"};
arr.Split(x => x.EndsWith("e"));
Run Code Online (Sandbox Code Playgroud)

以下任何一种都可以:

IEnumerable<string> {{}, {"Two"}, {}, {"Four", "Seven"}, {}}
IEnumerable<string> {{"Two"}, {"Four", "Seven"}}
Run Code Online (Sandbox Code Playgroud)

用于存储匹配的可选元素将是{"One", "Three", "Nine", "Five"}.

And*_*ndy 24

如果您想避免使用扩展方法,可以始终使用:

var arr = new[] {"One", "Two", "Three", "Nine", "Four", "Seven", "Five"};

var result = arr.ToLookup(x => x.EndsWith("e"));

// result[true]  == One Three Nine Five
// result[false] == Two Four Seven
Run Code Online (Sandbox Code Playgroud)


use*_*116 6

您应该通过扩展方法执行此操作(此方法假定您忽略分区项):

/// <summary>Splits an enumeration based on a predicate.</summary>
/// <remarks>
/// This method drops partitioning elements.
/// </remarks>
public static IEnumerable<IEnumerable<TSource>> Split<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> partitionBy,
    bool removeEmptyEntries = false,
    int count = -1)
{
    int yielded = 0;
    var items = new List<TSource>();
    foreach (var item in source)
    {
        if (!partitionBy(item))
            items.Add(item);
        else if (!removeEmptyEntries || items.Count > 0)
        {
            yield return items.ToArray();
            items.Clear();

            if (count > 0 && ++yielded == count) yield break;
        }
    }

    if (items.Count > 0) yield return items.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

  • @Arithmomaniac:您可以轻松修改此算法来处理这种情况。相反,我选择在 `String.Split` 之后对其进行建模。*在罗马的时候!* (2认同)