Используя LINQ, чтобы найти общий префикс? - PullRequest
2 голосов
/ 12 ноября 2009

У меня есть две последовательности:

IEnumerable<string> x = new[] { "a", "b", "c" };
IEnumerable<string> y = new[] { "a", "b", "d", "e" };

Я бы хотел найти общий префикс этих двух последовательностей (т. Е. "a", "b"). Есть ли лаконичный способ сделать это в LINQ?

Имейте в виду, что на самом деле это не IEnumerable<string>; они IEnumerable<PathComponent>, где у меня есть реализация IEqualityComparer<PathComponent>.

Ответы [ 3 ]

3 голосов
/ 12 ноября 2009

Упоминание Дикама о Zip привело меня к этому коду:

public static class EnumerableExtensions
{
    public delegate bool EqualityComparison<in T1, in T2>(T1 x, T2 y);
    public delegate bool EqualityComparison<in T>(T x, T y);

    public static IEnumerable<T> CommonPrefix<T>(
        this IEnumerable<T> xs,
        IEnumerable<T> ys)
    {
        return CommonPrefix(xs, ys, EqualityComparer<T>.Default.Equals);
    }

    public static IEnumerable<T> CommonPrefix<T>(
        this IEnumerable<T> xs,
        IEnumerable<T> ys,
        EqualityComparison<T> eq)
    {
        IEnumerator<T> x = xs.GetEnumerator();
        IEnumerator<T> y = ys.GetEnumerator();

        while (x.MoveNext() && y.MoveNext() && eq(x.Current, y.Current))
        {
            yield return x.Current;
        }
    }

    public static IEnumerable<TResult> CommonPrefix<T1, T2, TResult> (
        this IEnumerable<T1> xs,
        IEnumerable<T2> ys,
        EqualityComparison<T1, T2> eq,
        Func<T1, T2, TResult> selector)
    {
        IEnumerator<T1> x = xs.GetEnumerator();
        IEnumerator<T2> y = ys.GetEnumerator();

        while (x.MoveNext() && y.MoveNext() && eq(x.Current, y.Current))
        {
            yield return selector(x.Current, y.Current);
        }
    }
}
1 голос
/ 12 ноября 2009

Это работает, но я не знаю о производительности Skip () для второго массива:

x.TakeWhile((s, i) => y.Skip(i).FirstOrDefault() == s);

Редактировать: К сожалению, вот немного лучший подход:

x.TakeWhile((s, i) => y.ElementAt(i) == s); 
0 голосов
/ 12 ноября 2009

Может быть, вы могли бы сделать что-то вроде этого (не проверено):

x.TakeWhile((item, index) => y.Contains(item) && y.IndexOf(item) == index);

EDIT . IndexOf доступен только для массивов, поэтому сначала следует преобразовать y в массив. Кроме того, вам нужно изменить код для использования вашего IEqualityComparer.

...