10

IEnumerableat を述語で分割し、述語に相対的なインデックスでアイテムをグループ化するメソッドが欲しいです。たとえば、List<string>を満たす at 項目を分割し、x => MyRegex.Match(x).Successそのような一致がグループ化された「間にある」項目を使用できます。

その署名は何かの行に見える可能性があります

public static IEnumerable<IEnumerable<TSource>> Split<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate,
    int bool count
)

、場合によっては、すべての分割線を含む出力の余分な要素があります。

foreachこれをループよりも効率的かつ/またはコンパクトに実装する方法はありますか? LINQメソッドで実装できるはずだと思いますが、指を置くことはできません。

例:

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

以下のいずれかでOKです。

IEnumerable<string> {{}, {"Two"}, {}, {"Four", "Seven"}, {}}
IEnumerable<string> {{"Two"}, {"Four", "Seven"}}

一致を保存するためのオプションの要素は{"One", "Three", "Nine", "Five"}.

4

5 に答える 5

37

拡張メソッドを避けたい場合は、常に次を使用できます。

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
于 2013-08-12T22:54:35.630 に答える
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();
}
于 2012-07-11T17:44:34.097 に答える
3
public static IEnumerable<IEnumerable<TSource>> Split<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate)
{
    List<TSource> group = new List<TSource>();
    foreach (TSource item in source)
    {
        if (predicate(item))
        {
            yield return group.AsEnumerable();
            group = new List<TSource>();
        }
        else
        {
            group.Add(item);
        }
    }
    yield return group.AsEnumerable();
}
于 2012-07-11T17:47:12.117 に答える
1
public static IEnumerable<IEnumerable<TSource>> Partition<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    yield return source.Where(predicate);
    yield return source.Where(x => !predicate(x));
}

例:

var list = new List<int> { 1, 2, 3, 4, 5 };
var parts = list.Partition(x => x % 2 == 0);
var even = parts.ElementAt(0); // contains 2, 4
var odd = parts.ElementAt(1); // contains 1, 3, 5
于 2015-06-26T10:54:02.857 に答える