2015-06-22 194 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

我認爲這使得它更復雜.. –