Assign values from one list to another using LINQ
Solution 1
I would just build up a dictionary and use that:
Dictionary<int, string> map = sourceList.ToDictionary(x => x.Id, x => x.Name);
foreach (var item in destinationList)
if (map.ContainsKey(item.Id))
item.Name = map[item.Id];
destinationList.RemoveAll(x=> x.Name == null);
Solution 2
Hope this will your desired result. First join two list based on key(Id) and then set property value from sourceList.
var result = destinationList.Join(sourceList, d => d.Id, s => s.Id, (d, s) =>
{
d.Name = s.Name;
return d;
}).ToList();
Solution 3
Barring the last requirement of "avoid creating new destinationList" this should work
var newList = destinationList.Join(sourceList, d => d.Id, s => s.Id, (d, s) => s);
To take care of "avoid creating new destinationList", below can be used, which is not any different than looping thru whole list, except that it probably is less verbose.
destinationList.ForEach(d => {
var si = sourceList
.Where(s => s.Id == d.Id)
.FirstOrDefault();
d.Name = si != null ? si.Name : "";
});
destinationList.RemoveAll(d => string.IsNullOrEmpty(d.Name));
user1269810
Updated on July 05, 2022Comments
-
user1269810 almost 2 years
Hello I have a little problem with assigning property values from one lists items to anothers. I know i could solve it "the old way" by iterating through both lists etc. but I am looking for more elegant solution using LINQ.
Let's start with the code ...
class SourceType { public int Id; public string Name; // other properties } class DestinationType { public int Id; public string Name; // other properties } List<SourceType> sourceList = new List<SourceType>(); sourceList.Add(new SourceType { Id = 1, Name = "1111" }); sourceList.Add(new SourceType { Id = 2, Name = "2222" }); sourceList.Add(new SourceType { Id = 3, Name = "3333" }); sourceList.Add(new SourceType { Id = 5, Name = "5555" }); List<DestinationType> destinationList = new List<DestinationType>(); destinationList.Add(new DestinationType { Id = 1, Name = null }); destinationList.Add(new DestinationType { Id = 2, Name = null }); destinationList.Add(new DestinationType { Id = 3, Name = null }); destinationList.Add(new DestinationType { Id = 4, Name = null });
I would like to achieve the following:
- destinationList should be filled with Names of corresponding entries (by Id) in sourceList
- destinationList should not contain entries that are not present in both lists at once (eg. Id: 4,5 should be eliminated) - something like inner join
- I would like to avoid creating new destinationList with updated entries because both lists already exist and are very large, so no "convert" or "select new".
In the end destinationList should contain:
1 "1111" 2 "2222" 3 "3333"
Is there some kind of elegant (one line Lambda? ;) solution to this using LINQ ?
Any help will be greatly appreciated! Thanks!
-
BrokenGlass about 12 yearsThis is
O(n^2)
- use a dictionary for lookup instead -
amit_g about 12 years@BrokenGlass, you mean O(n). The dictionary lookup should be much faster even with insertion. Ideally these lists should probably be dictionary to begin with (assuming Id are unique).
-
user1269810 about 12 years@amit_g - I experimented with join, very interesting, but i couldn't further assign the corresponding name. The second is also interesting...
-
amit_g about 12 yearsWhat do you mean by "i couldn't further assign the corresponding name."? The first one is selecting the source that already has Name in it. Please note that these are not the most efficient way of doing it if the lists are very long. If you have very long lists, use answer posted by @BrokenGlass or at least perform benchmarks.
-
BrokenGlass about 12 years@amit_g: I didn't mean O(n) - your code is O(n^2) since you do a
Foreach
= O(n) and a nestedWhere(..)
which is alsoO(n)
-> so it'sO(n^2)
-
user1269810 about 12 years@amit_g - Well yes but this Join returns sourceList with Name, I need destinationList to be filled with that corresponding Name from source. But anyways this is an interesting example :)
-
user1269810 about 12 yearsHmm, yes, this looks very promising! You are right, performance is at stake here. Seems like the best answer to my problem, I'll explore it further. Thanks!
-
amit_g about 12 years@user1269810, the first method is not modifying any list but is creating a new one and returning it. So you could do destinationList = destinationList.Join(...) but regardless of how it is written, in that method, the existing lists are not modified, a new one is created.
-
user1269810 about 12 years@amit_g - Okay, well, one cannot have everything :)
-
user1269810 about 12 yearsOK, this is it. Not exactly what I imagined but it works perfectly. Thank you!
-
Milind Thakkar almost 6 yearsThis saved my day ! Thanks !!