Давайте реализуем (в общем случае ) это с помощью Linq :
using System.Linq;
...
private static IEnumerable<T[]> Differences<T>(IEnumerable<IEnumerable<T>> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
if (null == comparer)
comparer = EqualityComparer<T>.Default;
if (null == comparer)
throw new ArgumentNullException(nameof(comparer),
$"No default comparer for {typeof(T).Name}");
Dictionary<T, int> prior = null;
foreach (var line in source) {
Dictionary<T, int> current = line
.GroupBy(item => item, comparer)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);
if (null != prior)
yield return current
.Where(item => prior.ContainsKey(item.Key))
.SelectMany(item => Enumerable
.Repeat(item.Key, Math.Min(item.Value, prior[item.Key])))
.ToArray();
prior = current;
}
}
Демо:
List<string[]> list = new List<string[]>() {
new [] { "some", "random", "string" },
new [] { "some", "other", "random", "string" },
new [] { "some", "some", "some" },
new [] { "some", "some", "other" },
new [] { "some", "other", "some" },
};
string demo = string.Join(Environment.NewLine, Differences(list)
.Select(line => string.Join(", ", line)));
Console.Write(demo);
Результат:
some, random, string // 1st and 2nd strings
some // 2nd and 3d strings
some, some // 3d and 4th strings
some, some, other // 4th and 5th strings
Если вы хотите, чтобы только 1-я строка , добавьте .FirstOrDefault():
string demo = Differences(list)
.Select(line => string.Join(", ", line))
.FirstOrDefault();
Console.Write(demo);
Результат:
some, random, string
Наконец, если вы хотите пересечь все элементы (общие элементы во всех строках):
private static IEnumerable<T> IntersectAll<T>(IEnumerable<IEnumerable<T>> source,
IEqualityComparer<T> comparer = null) {
if (null == source)
throw new ArgumentNullException(nameof(source));
if (null == comparer)
comparer = EqualityComparer<T>.Default;
if (null == comparer)
throw new ArgumentNullException(nameof(comparer),
$"No default comparer for {typeof(T).Name}");
Dictionary<T, int> prior = null;
foreach (var line in source) {
Dictionary<T, int> current = line
.GroupBy(item => item, comparer)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count(), comparer);
if (null != prior)
prior = current
.Where(item => prior.ContainsKey(item.Key))
.ToDictionary(item => item.Key, item => Math.Min(item.Value, prior[item.Key]));
else
prior = current;
}
return (prior ?? new Dictionary<T, int>())
.SelectMany(item => Enumerable.Repeat(item.Key, item.Value));
}