使用LINQ将值从一个列表分配给另一个列表

时间:2012-03-14 18:50:58

标签: c# .net linq list lambda

您好我将一个列表项的属性值分配给其他人有一点问题。我知道我可以通过迭代两个列表来解决它“旧方法”但我正在寻找使用LINQ的更优雅的解决方案。

让我们从代码开始......

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 });

我想实现以下目标:

  • destinationList应填充sourceList
  • 中相应条目的名称(通过Id)
  • destinationList不应包含一次不存在于两个列表中的条目(例如,Id:4,5应该被删除) - 类似于内连接
  • 我想避免使用更新的条目创建新的destinationList,因为这两个列表已经存在且非常大, 所以没有“转换”或“选择新”。

最终destinationList应包含:

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

使用LINQ是否有某种优雅(一线Lambda?)解决方案?

任何帮助将不胜感激!谢谢!

5 个答案:

答案 0 :(得分:8)

我只是建立一个字典并使用它:

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);

答案 1 :(得分:5)

希望这将是你想要的结果。首先根据键(Id)连接两个列表,然后从sourceList设置属性值。

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

答案 2 :(得分:4)

除了“避免创建新的目标列表”的最后要求,这应该可行

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

要注意“避免创建新的目标列表”,可以使用下面的内容,这与通过整个列表循环没有任何不同,除了它可能不那么详细。

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));

答案 3 :(得分:0)

坦率地说,这是最简单的:

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();

你可以用Join做一些丑陋的事情,但我不会打扰。

答案 4 :(得分:0)

我希望这对你有用。最后,destinationList具有正确的数据,而不创建任何类型的新列表。

        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;
            }
        });