Можно ли как-нибудь применить особый Comparer при соединении 2-ух последовательностей синтаксисом запросов?
Например, есть 2 листа и я хочу их без учета регистра соединить.
Конечно я могу между equals все привести в верхний регистр, но это не совсем верно.
Можно ли как-то задать метод сравнения явно?
static List<(string, string)> GetDifferent(IEnumerable<string> list1, IEnumerable<string> list2)
{
var left = from item1 in list1
join item2 in list2 on item1.ToUpper() equals item2.ToUpper()
into temp
from item2 in temp.DefaultIfEmpty()
select (item1, item2);
var right = from item2 in list2
join item1 in list1 on item2.ToUpper() equals item1.ToUpper()
into temp
from item1 in temp.DefaultIfEmpty()
select (item1, item2);
return left.Union(right).Where(x => x.Item1 == null || x.Item2 == null).ToList();
}
В query-syntax для join доступен лишь оператор равенства equals.
Однако, метод Join имеет перегрузку принимающую IEqualityComparer.
Так как в коде left outer join, то следует использовать метод GroupJoin, который также имеет перегрузку принимающую IEqualityComparer.
Например:
IEqualityComparer ec = ...;
var left = list1.GroupJoin(
list2,
item1 => item1,
item2 => item2,
(item1, items2) => new {item1, items2}
ec
).SelectMany(
item => item.items2.DefaultIfEmpty(),
(item, item2) => (item.item1, item2)
);
В синтаксисе запросов linq в join можно указать только точное соответствие: equals. Но можно вместо него использовать where и там уже использовать компаратор.
Аналогом этого кода:
from item1 in list1
join item2 in list2
on item1.ToUpper() equals item2.ToUpper()
select (item1, item2);
будет следующий:
from item1 in list1
from item2 in list2
where item1.Equals(item2, StringComparison.OrdinalIgnoreCase)
select (item1, item2);
Но я затрудняюсь преобразовать в эту форму код с использованием into.
Для исключения элементов одной последовательности из другой можно (нужно) применять метод Except:
list1.Except(list2, StringComparer.OrdinalIgnoreCase)
list2.Except(list1, StringComparer.OrdinalIgnoreCase)
Соответственно, полный код может выглядеть как-то так:
var left = list1.Except(list2, StringComparer.OrdinalIgnoreCase)
.Select(item => (item, (string)null));
var right = list2.Except(list1, StringComparer.OrdinalIgnoreCase)
.Select(item => ((string)null, item));
return left.Union(right).ToList();
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости