let's say I have two collections:
string[] arr1 =
{
"item-1",
"item-2",
"item-3",
"item-777",
"item-4"
};
string[] arr2 =
{
"item-1",
"item-2",
"item-3",
"item-4"
};
TODO: when arr1 element does not match to arr2 element, return: arr1[i] = "empty". return type: IEnumerable<(string, string)>. result should be:
item-1 - item-1
item-2 - item-2
item-3 - item-3
item-777 - empty
item-4 - item-4
My solution doesn't works:
IEnumerable<(string, string)> result = arr1.Join(arr2,
item => item,
item => item ?? "empty",
(item1, item2) => (item1, item2));
foreach (var item in result)
{
Console.WriteLine($"{item.Item1} - {item.Item2}");
}
Please help.
CodePudding user response:
Sometimes these things are just easier to write with the other syntax
IEnumerable<(string, string)> result = from a1 in arr1
join a2 in arr2 on a1 equals a2 into j
from a2item in j.DefaultIfEmpty()
select (a1,a2item ?? "empty");
Live example: https://dotnetfiddle.net/tFMNxA
In method syntax it uses GroupJoin
and SelectMany
var result = arr1.GroupJoin(arr2, a1 => a1, a2 => a2, (a1,a2) => (a1,a2))
.SelectMany(x => x.a2.DefaultIfEmpty(), (x,y) => (Item1:x.a1, Item2: y?? "empty"));
Live example: https://dotnetfiddle.net/MbBIyQ
CodePudding user response:
With HashSet<T>
you can "quickly" find if given item exists in second array. Join
method will use HashSet in "background" anyway.
var others = arr2.ToHashSet();
var pairs = arr1.Select(item => (item, others.Contains(item) ? item : "empty"));
foreach (var pair in pairs)
{
Console.WriteLine($"{pair.First} - {pair.Second}");
}