比较两个List元素,如果id为equals则替换

时间:2018-05-24 09:59:35

标签: c# linq

我有两个带有类的列表

public class Product 
{
  int id;
  string url;
  ect.
}

我需要在旧列表(10k +元素)中按ID比较新列表(10个元素) 如果id相同,则只需将新列表中的数据替换为旧列表

我认为使用LINQ会很好。 你能帮帮我怎样才能使用LINQ或者有击球手库?

5 个答案:

答案 0 :(得分:1)

您是否需要修改集合或返回新集合?

如果您要返回新的收藏品,可以

var query = from x in oldItems
            join y in newItems on y.Id equals x.Id into g
            from z in g.DefaultIfEmpty()
            select z ?? x;
var new List = query.ToList();

此方法将忽略newItems中旧项目中不存在的条目。

如果您要修改集合,最好使用字典并在任何地方引用它。

您可以通过

从列表中创建字典
var collection = items.ToDictionary(x => x.Id, x => x);

注意修改字典不会改变源集合,我们的想法是用字典对象替换你的集合。

如果您正在使用字典,则可以迭代新集合并检查密钥。

foreach (var item in newItems.Where(x => collection.ContainsKey(x.Id))) {
  collection[item.Id] = item;
}

字典是可迭代的,因此您可以根据需要循环遍历Values集合。添加和删​​除很快,因为您可以通过键引用。我能想到的唯一问题是你是否依赖于集合的排序。

如果您需要使用原始集合类型,则可以在newItems集合上使用ToDictionary消息。这使您的更新代码看起来像这样。

var converted = newItems.ToDictionary(x => x.Id, x => x);
for (var i = 0; i < oldItems.Count(); i++) {
  if (converted.ContainsKey(oldItems[i].Id)) {
    oldItems[i] = converted[oldItems[i].Id];
  }
}

这样做的好处是你只需要循环一次newitems集合,然后再进行密钥查找,因此它的cpu密集度较低。缺点是你已经为newitems创建了一个新的密钥集合,因此它消耗了更多的内存。

答案 1 :(得分:0)

向您发送一个示例函数,该函数通过两个列表的id属性连接两个列表,然后使用较新的列表更新原始Product.url

void ChangeItems(IList<Product> original, IList<Product> newer){      
    original.Join(newer, o => o.id, n => n.id, (o, n) => new { original = o, newer = n })
            .ToList()
            .ForEach(j => j.original.Url = j.newer.Url);            
}

答案 2 :(得分:0)

解决方案: - :您正在寻找的LINQ解决方案将是这样的

oldList = oldList.Select(ele => { return (newList.Any(i => i.id == ele.id) ? newList.FirstOrDefault(newObj => newObj.id == ele.id) : ele); }).ToList();

注意: - 我们在此处根据OldList创建NewList&amp; OldList,即我们正在用NewList object替换OldList object。如果您只想要一些新的List属性,可以在类中创建一个复制方法

复制构造函数的EG

 oldList = oldList.Select(ele => { return (newList.Any(i => i.id == ele.id) ? ele.Copy(newList.FirstOrDefault(newObj => newObj.id == ele.id)) : ele); }).ToList();

//Changes in your class
public void Copy(Product prod)
{
    //use req. property of prod. to be replaced the old class 
    this.id = prod.id;
}

<强>

  

即使使用linq迭代超过10k +元素也不是一个好主意,因为它仍会影响你的CPU performance *

Online sample for 1st solution

答案 3 :(得分:0)

你上课了

public class Product
{
    public int id;
    public string url;
    public string otherData;
    public Product(int id, string url, string otherData)
    {
        this.id = id;
        this.url = url;
        this.otherData = otherData;
    }
    public Product ChangeProp(Product newProd)
    {
        this.url = newProd.url;
        this.otherData = newProd.otherData;
        return this;
    }
}

注意,现在我们在数据类中有ChangeProp方法,此方法将接受新类并使用新类的属性修改旧类并返回修改后的新类(如您所愿)你的旧类被替换为新的类属性(数据)。所以最后Linq将是可读和干净的。

你已经有oldList有很多条目,如果id相同,必须用newList的数据替换oldList的数据,你可以像下面这样做。

假设他们有以下数据,

    List<Product> oldList = new List<Product>();
    for (int i = 0; i < 10000; i++)
    {
        oldList.Add(new Product(i, "OldData" + i.ToString(), "OldData" + i.ToString() + "-other"));
    }
    List<Product> newList = new List<Product>();
    for (int i = 0; i < 5; i++)
    {
        newList.Add(new Product(i, "NewData" + i.ToString(), "NewData" + i.ToString() + "-other"));
    }

Linq将完成您的工作。

    oldList.Where(x => newList.Any(y => y.id == x.id))
        .Select(z => oldList[oldList.IndexOf(z)].ChangeProp(newList.Where(a => a.id == z.id).FirstOrDefault())).ToList();

答案 4 :(得分:0)

foreach(var product in newList)
{
  int index = oldList.FindIndex(x => x.id == product.id);
  if (index != -1)
   {
     oldList[index].url = product.url;
   }
}

这将有效,我认为它也是一个更好的解决方案。 以上所有解决方案都是在内存中创建新对象并使用10k +创建新列表 记录绝对是个坏主意。 请在产品中填写字段,因为它无法访问。