在 C# 中更新项目列表

Update list of items in c#

我想知道您是否可以建议我一种在 C# 中更新项目列表的有效方法。这是一个通用示例:

如果 CurrentList 是

[ {Id: 154, Name: "George", Salary: 10 000}
  {Id: 233, Name: "Alice", Salary: 10 000}]

NewList 是

[ {Id: 154, Name: "George", Salary: 25 000}
  {Id: 234, Name: "Bob", Salary: 10 000}]

那么结果应该是:

[{Id: 154, Name: "George", Salary: 25 000} 
{Id: 234, Name: "Bob", Salary: 10 000} ]

我不想只清除第一个并使用第二个的值,而是想更新具有相同 ID 的那些,删除已删除的那些并添加任何新的。

提前致谢。

我会这样做:(对于普通列表)

// the current list
var currentList = new List<Employee>();
currentList.Add(new Employee { Id = 154, Name = "George", Salary = 10000 });
currentList.Add(new Employee { Id = 233, Name = "Alice", Salary = 10000 });

// new list
var newList = new List<Employee>();
newList.Add(new Employee { Id = 154, Name = "George", Salary = 25000 });
newList.Add(new Employee { Id = 234, Name = "Bob", Salary = 10000 });

// clean up
foreach (var oldEmployee in currentList.ToArray())
    if (!newList.Any(item => oldEmployee.Id == item.Id))
        currentList.Remove(oldEmployee);

// check if the new item is found within the currentlist. 
// If so? update it's values else add the object.
foreach (var newEmployee in newList)
{
    var oldEmployee = currentList.FirstOrDefault(item => item.Id == newEmployee.Id);
    if (oldEmployee == null)
    {
        // add
        currentList.Add(newEmployee);
    }
    else
    {
        // modify
        oldEmployee.Name = newEmployee.Name;
        oldEmployee.Salary = newEmployee.Salary;
    }
}

您可以使用词典加快速度,但这不是您的问题(暂时)

您可以使用 for 循环和 Linq 表达式来完成:

        for (int i = 0; i < NewList.Count; i++)
        {
            var record = CurrentList.FirstOrDefault(item => item.Id == NewList[i].Id);
            if (record == null) { CurrentList.Add(NewList[i]); }
            else { record.Id = NewList[i].Id; record.Name = NewList[i].Name; record.Salary = NewList[i].Salary; }
        }

        CurrentList.RemoveAll(item => NewList.FirstOrDefault(item2 => item2.Id == item.Id) == null);

使用示例: Example

包含在扩展方法中的 LINQ'y 版本,如果 'Id' 在某种接口上,可以修改为通用的。

合并操作可能是实体对象(例如员工)上的 Merge() 方法,但我在这里选择使用委托。

public class Tests
{
    [Test]
    public void MergeSpike()
    {
        // the current list
        var currentList = new List<Employee>();
        currentList.Add(new Employee { Id = 154, Name = "George", Salary = 10000 });
        currentList.Add(new Employee { Id = 233, Name = "Alice", Salary = 10000 });

        // new list
        var newList = new List<Employee>();
        newList.Add(new Employee { Id = 154, Name = "George", Salary = 25000 });
        newList.Add(new Employee { Id = 234, Name = "Bob", Salary = 30000 });

        currentList.Merge(newList, (o, n) =>
        {
            if(o.Id != n.Id) throw new ArgumentOutOfRangeException("Attempt to merge on mismatched IDs");
            o.Name = n.Name;
            o.Salary = n.Salary;
        });


        Assert.That(currentList.Count(), Is.EqualTo(2));
        Assert.That(currentList.First(c => c.Id == 154).Salary, Is.EqualTo(25000));
        Assert.That(currentList.Any(c => c.Id == 233), Is.False);
        Assert.That(currentList.First(c => c.Id == 234).Salary, Is.EqualTo(30000));


    }
}

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Salary { get; set; }
}

public static class EmployeeListExtensions
{
    public static void Merge(this List<Employee> currentList, IEnumerable<Employee> newList, Action<Employee, Employee> merge)
    {
        // Updates
        currentList.Where(e => newList.Any(n => n.Id == e.Id))
            .ToList().ForEach(e => merge(e, newList.First(n1 => n1.Id == e.Id)));

        // Deletes
        var remove = currentList.Where(cl => newList.All(nl => cl.Id != nl.Id)).ToList();
        currentList.RemoveAll(e => remove.Any(r => r.Id == e.Id));

        // Inserts
        currentList.AddRange(newList.Where(nl => currentList.Any(c => c.Id != nl.Id)));
    }
}