2009-08-19 5 views
6

У меня есть два List<T> объекты:Объединить и обновления двух списков в C#

Например:

лист 1:
ID, значение, где Id заполняется и значением является пустым, и он содержит сказать, идентификаторы от 1 до 10.
1 ""
2 ""
...
10 ""

Список 2:
ID, значения и другие атрибуты, заполненные значениями, но этот список является подмножеством списка 1 в терминах идентификаторов. (например только 3 элементы)
2,67
4,90
5,98

То, что я хочу, это сводный список 1, но с обновленными значениями. У кого-нибудь есть хороший метод расширения, который сделает это или любой изящный код для выполнения этой операции. Окончательный список должен быть:

идентификатор Значение
1 ""
2,67 // значение из списка 2
3 ""
4,90
5,98
6, ""
...
10 ""

+0

Ваш * Value * строка или INT? Кажется, вы показываете строки в List 1, тогда как ints в List 2. – Noldorin

ответ

3

я бы, вероятно, использовать словарь, а не список:

// sample data 
    var original = new Dictionary<int, int?>(); 
    for (int i = 1; i <= 10; i++) 
    { 
     original.Add(i, null); 
    } 
    var updated = new Dictionary<int, int>(); 
    updated.Add(2, 67); 
    updated.Add(4, 90); 
    updated.Add(5, 98); 
    updated.Add(11, 20); // add 

    // merge 
    foreach (var pair in updated) 
    { 
     original[pair.Key] = pair.Value; 
    } 

    // show results 
    foreach (var pair in original.OrderBy(x => x.Key)) 
    { 
     Console.WriteLine(pair.Key + ": " + pair.Value); 
    } 

Если говорить о свойства объекта, это будет сложнее, но все же выполнимая.

+0

Спасибо, это то, что я ухаживал за .... – chugh97

3

Это O (м * п), но должен делать эту работу для произвольных списков

 foreach (var record in List1) 
     { 
      var other = List2.FirstOrDefault(x => x.Key == record.Key); 
      if(other != null) record.Value = other.Value; 
     } 

Если список гарантированно заказан, его можно свести к O (n) за счет большего количества кода. Algortihm будет

Current items start as head of each list 
While items remain in both lists 
    If the current item of list1 has lower key than list2 advance to next in list1 
    else if the current item of list2 has lower key than list1 advance to next in list2 
    else copy value from current list2 item into list1 item and advance both lists. 
0

Если у вас есть оба списка, отсортированного по ID, вы можете использовать вариацию классического алгоритма слияния:

int pos = 0; 
foreach (var e in list2) { 
    pos = list1.FindIndex(pos, x => x.Id==e.Id); 
    list1[pos].Value = e.Value; 
} 

Обратите внимание, что это также требует list2 быть строгим подмножеством list1 по ID (т.е. list1 действительно содержит все идентификаторы list2)

конечно, вы также можете обернуть это в метод расширения

public static void UpdateWith<T>(this List<T> list1, List<T> list2) 
where T:SomeIdValueSupertype { 
    int pos = 0; 
    foreach (var e in list2) { 
    pos = list1.FindIndex(pos, x => x.Id==e.Id); 
    list1[pos].Value = e.Value; 
    } 
} 
9

использование linq: список1 = список2.Союз (песни1);

+0

Я пробовал ваш код с двумя списками типа 'list ' ученик класса выглядит следующим образом: 'Student student = new Student() {Id = 1, Name = "foo"} 'Используя этот синтаксис' list1 = list2.ToList(). Union (list1.ToList()). ToList(); 'но он не объединил два списка; он просто склеивает их, как [UNION - пример 3] (http://stackoverflow.com/questions/49925/what-is-the-difference-between-union-and-union-all). Вы уверены, что он «объединяет список с обновленными значениями»? – surfmuggle

+0

Я нашел этот вопрос о том, как [удалить дубликаты при слиянии списков] (http://stackoverflow.com/questions/16980485/remove-duplicates-while-merging-lists-using-union-in-linq), и это подтверждает, что ваш код работает только в том случае, если класс переопределяет 'GetHashCode()' и 'Equals()' – surfmuggle

0
private void btnSearch_Click(object sender, EventArgs e) 
{ 
String searchBy = cmbSearchBy.Text.ToString(); 
String searchFor = txtSearchFor.Text.Trim(); 

var List3 = (from row in JobTitleDB.jobList 
         where (row.JID.ToString()+row.JobTitleName.ToString().ToLower()).Contains(searchFor.ToLower()) 
         select row).ToList(); 
if (searchBy == "All") 
      { 
       dgJobTitles.DataSource = null; 
       //dgJobTitles.DataSource = List1; 
       //dgJobTitles.DataSource = List2; 
       //dgJobTitles.DataSource = List1.Concat(List2); 
       //dgJobTitles.DataSource = List1.Union(List2); 
       dgJobTitles.DataSource = List3; 
       //dgJobTitles.DataSource=List1.AddRange(List2); 
      } 
} 
+0

. Пожалуйста, предоставьте здесь некоторое объяснение. Удалите ненужный прокомментированный код. – BuddhiP

0
Dictionary<int, string> List1 = new Dictionary<int, string>(); 
List1.Add(1,""); 
List1.Add(2,""); 
List1.Add(3,""); 
List1.Add(4,""); 
List1.Add(5,""); 
List1.Add(6,""); 

Dictionary<int, string> List2 = new Dictionary<int, string>(); 
List2.Add(2, "two"); 
List2.Add(4, "four"); 
List2.Add(6, "six"); 

var Result = List1.Select(x => new KeyValuePair<int, string>(x.Key, List2.ContainsKey(x.Key) ? List2[x.Key] : x.Value)).ToList(); 
Смежные вопросы