Хорошо, как насчет этого, у него есть преимущество в том, что он максимизирует ленивые вычисления и минимизирует манипуляции со строками.
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();
}
по сути, он группирует каждую сторону по char, а затем находит символы, у которых есть группа с обеих сторон. Совпавшие группы учитываются последовательно, пока не закончится одна из них. Эти подсчеты суммируются для получения результата.
Было бы тривиально выполнить это в общем случае для любых двух последовательностей. Смотри ниже,
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();
person
Jodrell
schedule
13.02.2014