好的,那这样做的优点在于最大化懒惰求值并最小化字符串操作。
public int CommonChars(string left, string right)
{
return left.GroupBy(c => c)
.Join(
right.GroupBy(c => c),
g => g.Key,
g => g.Key,
(lg, rg) => lg.Zip(rg, (l, r) => l).Count())
.Sum();
}
基本上,它将每一边按字符进行分组,然后找到在两侧都有组的字符。匹配的组成对地计算,直到其中一个用完为止。这些计数求和以产生结果。
对于任何两个序列,执行此操作通常很简单。请参见下面。
public static int CommomCount<T>(
this IEnumerable<T> source,
IEnumerable<T> sequence,
IEqualityComparer<T> comparer = null)
{
if (sequence == null)
{
return 0;
}
if (comparer == null)
{
comparer = EqualityComparer<T>.Default;
}
return source.GroupBy(t => t, comparer)
.Join(
sequence.GroupBy(t => t, comparer),
g => g.Key,
g => g.Key,
(lg, rg) => lg.Zip(rg, (l, r) => l).Count(),
comparer)
.Sum();
}
您可以像这样使用它。
"G12AA".CommonCount("GAA2")
可选的
comparer
参数在需要忽略大小写或其他特殊处理时可能会很有用。
为了重复利用性,我倾向于删除
Sum()
并返回一个
IEnumerable<T>
,然后在调用中添加求和,像这样:
public static IEnumerable<T> Commom<T>(
this IEnumerable<T> source,
IEnumerable<T> sequence,
IEqualityComparer<T> comparer = null)
{
if (sequence == null)
{
return Enumerable.Empty<T>();
}
if (comparer == null)
{
comparer = EqualityComparer<T>.Default;
}
return source.GroupBy(t => t, comparer)
.Join(
sequence.GroupBy(t => t, comparer),
g => g.Key,
g => g.Key,
(lg, rg) => lg.Zip(rg, (l, r) => l),
comparer)
.SelectMany(g => g);
}
所以你可以轻松地做到
Console.WriteLine(new string("G12AA".Common("GAA2").ToArray()));
或者只是原始的。
"G12AA".Common("GAA2").Count();