2016-11-10 5 views
1

Я много сделал, и я не могу найти ответ на эту конкретную проблему; ответы на подобные проблемы, но ничего подобного.Слияние двух списков и объединение значений объектов

По существу, я пытаюсь сделать два списка C#, оба из которых содержат ряд объектов C#, состоящих из пар целых целых чисел, затем объединяют их вместе, объединяя значения аналогичных объектов.

Предположим, что мой класс объектов выглядит следующим образом;

public class Object 
{ 
    public string Name; 
    public int Value; 
} 

И мы также скажем, что мои списки выглядят так:

objectList1    objectList2 
Name  Value  Name  Value 
Object1  1  Object1  1 
Object2  1  Object2  1 
Object3  1 
Object4  1 
Object5  1 

Моя цель здесь, чтобы объединить содержимое объектов objectList2 «s для соответствующих объектов в objectList1. В этом примере это означало бы, что objectList1 будет выглядеть так, когда все будет сказано и сделано;

Name  Value 
Object1  2 
Object2  2 
Object3  1 
Object4  1 
Object5  1 

Теперь я знаю, что это возможно сделать с foreach и FindIndex() звонков, но я почти уверен, что есть более эффективный способ пойти об этом. Если я ошибаюсь, все в порядке, но я хотел бы знать, могу ли я это оптимизировать, потому что моя кишка говорит мне, что должен быть более простой способ.

+0

Вам необходимо предоставить метрики для _efficient_ и _optimize_. Меньше строк кода? Меньше кэша второго уровня? Меньше строк сравнения? Уменьшение использования памяти? Покажите код, который вы используете, и опишите проблему, с которой вы столкнулись. Тогда мы сможем помочь вашему кишечнику. – HABO

+0

Я в основном имел в виду неотъемлемую неэффективность циклов foreach. Я пошел с опцией «Словари», потому что мгновенное местоположение по ключевым значениям намного более эффективно в этом случае. – PorkchopDonut

ответ

1

Лучший вариант я могу думать о том, чтобы использовать словарь, предполагая, что все ключи уникальны

сделайте foreach на меньшем словаре (не показано ниже), проверяя соответствие совпадающих ключей в другом, а затем измените, если найдено или добавление, если не найдено (обратите внимание, что этот алгоритм является разрушительным, сделать копию, чтобы вернуться, если вы хотите сохранить оригиналы)

void Merge (Dictionary<string, int> a, Dictionary<string, int> b) 
    { 
     foreach (string key in a.Keys) 
     { 
      if (b.ContainsKey(key)) 
      { 
       b[key] = b[key] + a[key]; 
      } 
      else 
      { 
       b.Add(key, a[key]); 
      } 
     } 
    } 
+0

Я не знаю, почему я не использовал словари в первую очередь>. <Это, безусловно, лучший путь в этом сценарии! Спасибо огромное! – PorkchopDonut

+0

@PorkchopDonut В моем ответе есть все Linq и немного более простой подход, если хотите. Возможно, это не так эффективно. – Greg

1

Я считаю, что вы хотите сделать:

var contents = sample.Concat(example).GroupBy(n => n.Name); 

В основном это создаст группировку, но она добавит список вместе. Затем группа основана на имени, которое будет содержать числовой показатель того, сколько из того же имени существует. В основном, вы получаете IGrouping<Key, Value>.

Например:

var merge = new List<Content>(); 
var contents = sample.Concat(example).GroupBy(n => n.Name); 
foreach(var item in contents) 
    merge.Add(new Content() { Name = item.Key, Value = item.Sum(value => value.Value) }); 

Вы могли бы также сделать это со всеми Linq, если вы хотите:

var contents = example.Concat(sample) 
     .GroupBy(n => n.Name) 
     .SelectMany(content => 
        content.Select((item, i) => new { Name = content.Key, Value = content.Sum(v => v.Value) }).Distinct()); 
1

Вы можете использовать LINQ, как показано ниже

var list1 = new List<Object>(); 
list1.Add(new Object { Name = "Object1", Value = 1 }); 
list1.Add(new Object { Name = "Object2", Value = 1 }); 
list1.Add(new Object { Name = "Object3", Value = 1 }); 
list1.Add(new Object { Name = "Object4", Value = 1 }); 
list1.Add(new Object { Name = "Object5", Value = 1 }); 
var list2 = new List<Object>(); 
list2.Add(new Object { Name = "Object1", Value = 1 }); 
list2.Add(new Object { Name = "Object2", Value = 1 }); 

var total = from item1 in list1 
      join item2 in list2 
      on item1.Name equals item2.Name into list3 
      from subset in list3.DefaultIfEmpty() 
      select new Object 
      { 
       Name = item1.Name, 
       Value = item1.Value + (subset == null ? 0 : subset.Value) 
      }; 
Смежные вопросы