我有两个序列:
IEnumerable<string> x = new[] { "a", "b", "c" };
IEnumerable<string> y = new[] { "a", "b", "d", "e" };
我想找到这两个序列的公共前缀(即"a", "b"
)。在LINQ中有一个简洁的方法吗?
请记住,这些并非真正IEnumerable<string>
;他们是IEnumerable<PathComponent>
,我实施了IEqualityComparer<PathComponent>
。
答案 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。