使用LINQ查找公共前缀?

时间:2009-11-12 09:59:37

标签: linq linq-to-objects

我有两个序列:

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 个答案:

答案 0 :(得分:3)

Dykam提到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 :(得分:1)

这有效,但我不知道第二个数组上Skip()的性能:

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

编辑:哎呀 - 这是一个更好的方法:

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

答案 2 :(得分:0)

也许你可以做这样的事情(未经测试):

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

修改即可。 IndexOf仅在阵列上可用,因此您应首先将y转换为数组。此外,您需要修改代码以使用IEqualityComparer。