Reputation: 29301
I have two collections of elements. I am trying to take all elements in the first collection which have a matching ID in the second collection and run the CopyToDomain method against the matching elements.
The following code works fine, but I was a bit surprised by its verbosity. ReSharper isn't recommending anything here, but I was wondering if doing an intersection of the two collections and then mapping the method over the elements would be more clear? Would you make that change, or should I stop fussing and leave this as it is?
Task task = new Task();
IList<TaskAttributeDto> taskAttributeDtos = new List<TaskAttributeDto>();
taskAttributeDtos.Add(new TaskAttributeDto{ ID = 1});
taskAttributeDtos.Add(new TaskAttributeDto{ ID = 2});
foreach (TaskAttributeDto taskAttributeDto in taskAttributeDtos)
{
TaskAttribute matching = task.TaskAttributes.FirstOrDefault(t => t.ID == taskAttributeDto.ID);
if (matching != null)
{
taskAttributeDto.CopyToDomain(matching);
}
}
Upvotes: 4
Views: 155
Reputation: 110111
The original code finds the first match. A join finds all matches, and a group join allows you to pick a winner from each matching group.
var matches =
from dto in taskAttributesDtos
join attribute in task.TaskAttributes
on dto.ID equals attribute.ID
into attributeGroup //into clause causes GroupJoin to be called.
select new { dto, attribute = attributeGroup.First() };
foreach (var m in matches)
m.dto.CopyToDomain(m.attribute);
Upvotes: 0
Reputation: 2531
If you're concerned about the readability of query syntax, you can try using method syntax:
var matches = taskAttributesDtos.Join(task.TaskAttributes,
a => a.ID,
b => b.ID,
(a, b) => new { dto = a, attribute = b } );
foreach (var m in matches)
m.dto.CopyToDomain(m.attribute);
Upvotes: 2
Reputation: 734
foreach(TaskAttributeDto taskAttributeDto in taskAttributeDtos.Where(t1 => TaskAttributes .Any(t2 => t2.Id == t1.Id)))
{
taskAttributeDto.CopyToDomain(taskAttributeDto);
}
Upvotes: 2
Reputation: 292465
What you're doing is basically a join, so you can use the Linq join syntax:
var matches =
from dto in taskAttributesDtos
join attribute in task.TaskAttributes on dto.ID equals attribute.ID
select new { dto, attribute};
foreach (var m in matches)
m.dto.CopyToDomain(m.attribute);
Upvotes: 11
Reputation: 7336
task.TaskAttributes.Where(t => taskAttributeDtos.Select(d => d.ID).Contains(t.ID))
.ToList()
.ForEach(t => taskAttributeDtos.First(d => d.ID == t.ID).CopyToDomain(t));
Upvotes: 1