Assign values from one list to another using LINQ

2019-03-21 08:27发布

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!

5条回答
我只想做你的唯一
2楼-- · 2019-03-21 08:45

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);
查看更多
一夜七次
3楼-- · 2019-03-21 08:46

I hope this will be useful for you. At the end, destinationList has the correct data, without creating any new list of any kind.

        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;
            }
        });
查看更多
戒情不戒烟
4楼-- · 2019-03-21 08:47

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();
查看更多
我想做一个坏孩纸
5楼-- · 2019-03-21 08:48

Frankly, 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 could do something ugly with Join but I wouldn't bother.

查看更多
小情绪 Triste *
6楼-- · 2019-03-21 08:52

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));
查看更多
登录 后发表回答