2010-11-17 4 views
1

Я хотел бы объединить две записи, используя условие для каждого столбца в строке. Я бы дал вам образец кода, но я не знаю, с чего начать.Как объединить записи, используя LINQ?

class Foo 
{ 
    public int i {get;set;} 
    public int b{get;set;} 

    public string first{get;set;} 
    public string last{get;set;} 
    } 

//... 
    var list = new List<Foo>() { 
    new Foo() { i=1, b=0, first="Vince", last="P"}, 
    new Foo() { i=1, b=1, first="Vince", last="P"}, 
    new Foo() { i=1, b=0, first="Bob", last="Z"}, 
    new Foo() { i=0, b=1, first="Bob", last="Z"}, 
    } ; 

// This is how I'd like my result to look like 
// Record 1 - i = 1, b = 1, first="Vince", last = "P" 
// Record 2 - i = 1, b = 1, first="Bob", last = "Z" 
+0

Таким образом, чтобы уточнить, последний каждой группы Foo, упорядоченной по b, которая соответствует по полям i, first & last? – spender

+0

Как вы хотите объединить записи? Результат выглядит как вторая запись, но просто выбор одной из записей не предполагает слияния, так как должен определяться результат? – Guffa

+0

Если вы заметили, что b было объединено с равным 1. Поэтому я хочу выполнить операцию AND в свойстве b – 2010-11-17 01:11:54

ответ

1

Вы можете сгруппировать результат, а затем агрегировать поля из элементов в группе:

var result = list.GroupBy(f => f.first).Select(
    g => new Foo() { 
    b = g.Aggregate(0, (a, f) => a | f.b), 
    i = g.Aggregate(0, (a, f) => a | f.i), 
    first = g.Key, 
    last = g.First().last 
    } 
); 
0

Вы можете использовать метод Aggregate в LINQ.

Сначала добавьте метод Foo, скажем Merge, который возвращает новый Foo, основанный на ваших правилах слияния.

public Foo Merge (Foo other) 
{ 
    // Implement merge rules here ... 
    return new Foo {..., b=Math.Max(this.b, other,b), ...}; 

} 

Вы также можете создать вспомогательный метод вне класса Foo, который выполняет слияние.

Теперь используйте Aggregate над своим списком, используя первый элемент в качестве семени, объединив каждую запись с текущим суммарным значением по мере продвижения. Или, вместо того, чтобы использовать Aggregate (так как это несколько надуманный использование LINQ в данном случае), просто сделать:

Foo result = list.First(); 
foreach (var item in list.Skip(1)) result = result.Merge(item); 

Как указано ваши правила слияния?

+0

Я хочу выполнить операцию ИЛИ по свойству b – 2010-11-17 01:13:09

+0

Обновленный ответ с более подробной информацией. –

0

я нашел, не элегантное решение, которое работает

var result = list.GroupBy(i=>i.first); 
    foreach (IGrouping<string, Foo> grp in result) 
    { 
     grp.Aggregate ((f1, f2) => { 

      return new Foo() { 
       b = f1.b | f2.b, 
       i = f1.i | f2.i, 
       first = f1.first, 
       last = f1.last 
      }; 
     }); 
    } 
Смежные вопросы