2015-06-22 241 views
1

我想知道你是否可以建议我一种有效的方式来更新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的值,删除那些值已被删除并添加任何新的。

在此先感谢。

+0

是这个WPF或windows窗体,还是只是基本列表? –

+2

如果'Id'是一个唯一的标识符,那么我会考虑使用'Dictionary '等。它会使查找/添加/删除更容易 – DGibbs

+1

你有什么尝试?循环遍历新列表和更新CurrentList(或添加新列表),然后遍历当前列表并删除不在新列表中的东西的显而易见的解决方案似乎工作。你试过这个吗? – Chris

回答

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

可以加速这一过程,使用字典,但(现在)这不是你的问题

0

你可以

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

使用示例::与使用的for循环和LINQ表达做 Example

+0

是否有任何东西被删除?因为'CurrentList'中缺少的对象和'NewList'中的新对象在删除之前被添加。因此所有'Id's'都会出现在'CurrentList'中。 –

+0

只有那些在CurrentList中被删除但在NewList中找不到的对象被删除(因此这些对象的FirstOrDefault()方法将返回null)...查看图片...在我们的案例中,Michael被删除,因为对象与在新列表中找不到编号305 – Fabjan

0

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

合并操作可能是实体对象(如员工)上的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))); 
    } 
} 
+0

我认为这使得它更复杂.. –