Assigning values ​​from one list to another using LINQ

Hello, I have a small problem with assigning property values ​​from one list of elements to another. I know that I can solve this problem in the "old way", iterate through both lists, etc., but I'm looking for a 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 do the following:

  • destinationList must be filled with the names of the corresponding records (by identifier) ​​in sourceList
  • destinationList should not contain entries that are not present in both lists at the same time (for example, Id: 4,5 should be excluded) - something like an internal join
  • I would like to avoid creating a new mailing list with updated entries, because both lists already exist and are very large, so there is no “convert" or "choose new".

At the end, destinationList should contain:

 1 "1111" 2 "2222" 3 "3333" 

Is there any elegant (single line Lambda ?;) solution for this with LINQ?

Any help would be greatly appreciated! Thanks!

+4
source share
5 answers

I would just create a dictionary and use it:

 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); 
+5
source

Banning the last “avoid new mailing list” requirement should work

 var newList = destinationList.Join(sourceList, d => d.Id, s => s.Id, (d, s) => s); 

To take care to “avoid creating a new mailing list”, the following can be used, which does not differ from the cycle throughout the list, except that it is probably less detailed.

 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)); 
+4
source

Hope this is your desired result. First merge the two key-based lists (Id), and then set the property value from sourceList.

  var result = destinationList.Join(sourceList, d => d.Id, s => s.Id, (d, s) => { d.Name = s.Name; return d; }).ToList(); 
+2
source

Honestly, this is the simplest:

 var dictionary = sourceList.ToDictionary(x => x.Id, x => x.Name); foreach(var item in desitnationList) { if(dictionary.ContainsKey(item.Id)) { item.Name = dictionary[item.Id]; } } destinationList = destinationList.Where(x => x.Name != null).ToList(); 

You can do something ugly with Join , but I wouldn't worry.

0
source

I hope this will be helpful to you. In the end, destinationList has the correct data without creating any new lists of any type.

  destinationList.ForEach(x => { SourceType newSource = sourceList.Find(s=>s.Id == x.Id); if (newSource == null) { destinationList.Remove(destinationList.Find(d => d.Id == x.Id)); } else { x.Name = newSource.Name; } }); 
0
source

Source: https://habr.com/ru/post/1401449/


All Articles