更新c#中的项目列表

时间:2015-06-22 10:23:16

标签: c# linq list updates

我想知道您是否可以建议我更新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的值,删除已删除的值并添加任何新值。< / p>

提前致谢。

3 个答案:

答案 0 :(得分:2)

我会做这样的事情:(对于ordinairy列表)

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

你可以使用词典加快速度,但这不是你的问题(现在)

答案 1 :(得分:1)

你可以使用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

答案 2 :(得分:0)

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

合并Action可能是实体对象(例如employee)上的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)));
    }
}