2016-07-25 2 views
0

У меня есть большой набор данных, и я пытаюсь сгруппировать этот набор данных с помощью набора полей. В этом наборе данных у меня есть строки (балансов) в течение 5 последовательных дат. Моя цель - вернуть список настраиваемого объекта, который имеет поле IDictionary с ключом как Date и Balance как значение. Я попробовал что-то вроде:LINQ, чтобы сгруппировать список и вернуть список пользовательских объектов, которые имеют встроенный словарь

int[] DT = new int[] {20160725,20160726,20160727,20160728,20160729}; 
var tranformedData = 
posData 
.GroupBy(p => new {p.Symbol, p.Account}) 
.Select(gp => new TPosModel { 
    Symbol = gp.Key.Symbol, 
    Account = gp.Key.Account, 
    Balances = new Dictionary<int, decimal>{ 
    { 
     gp.Where(gpi => gpi.BusDate == DT[0]).Select(gpi => gpi.BusDate), 
     gp.Where(gpi => gpi.BusDate == DT[0]).Select(gpi => gpi.Balance) 
    }, 
    { 
     gp.Where(gpi => gpi.BusDate == DT[1]).Select(gpi => gpi.BusDate), 
     gp.Where(gpi => gpi.BusDate == DT[1]).Select(gpi => gpi.Balance) 
    }, 
    . 
    . 
    . 
} 

Этот код вызывает ошибку Duplicate Key. Я получил это, чтобы преобразовать словарь в список кортежей, но это не желаемый конечный результат. У кого-нибудь есть предложение о том, как это сделать, пожалуйста.

Благодаря

+0

Можете ли вы показать класс ввода? Также класс 'TPosModel'? –

+0

@YacoubMassad. Вход считывается в виде плоского файла и имеет следующий вид: «Список ({Symbol =« ABC.D », Account =« 1234-0C », BusDate = 20160725, Balance = 123.45}, {Symbol = «ABC.D», Account = «1234-0C», BusDate = 20160726, Balance = 125.67}, {Symbol = "BCD.E", Account = "2345-0D", BusDate = 20160725, Balance = -2300.5}, {Symbol = "BCD.E", Account = "2345-0D", BusDate = 20160726, Balance = -2350.5}) ' Этот список необходимо преобразовать в: ' Список ({Symbol = "ABC.D" , Account = "1234-0C", балансы = {[20160725,123.45], [20160726,125.67]}}, {Symbol = "BCD.E", Account = "2345-0D", балансы = {[20160725, - 2300.5] [20160726, -2350.5]}}) ' – skoppisetti

ответ

1

Похоже, что вам нужно сделать внутреннюю группу, на BusDate после отфильтровать любые, которые не DT, а затем вам нужно агрегировать Balance. Вы можете использовать Sum, так как у меня есть или что-то еще, например First().Balance. Это зависит только от того, как вы хотите обрабатывать несколько балансов в одну дату.

int[] DT = new int[] {20160725,20160726,20160727,20160728,20160729}; 
var tranformedData = 
posData 
.GroupBy(p => new {p.Symbol, p.Account}) 
.Select(gp => new TPosModel { 
    Symbol = gp.Key.Symbol, 
    Account = gp.Key.Account, 
    Balances = gp.Where(gpi => DT.Contians(gpi.BusDate)) 
       .GroupBy(gpi => gpi.BusDate) 
       .ToDictionary(g => g.Key, g => g.Sum(x => x.Balance) 
    }); 

В качестве примечания вы можете хранить вам даты, как DateTime вместо int.

+0

Спасибо, что работает. Это то, что я сделал: '... Балансы = gp.Where (GPI => DT.Contains (gpi.BusDate)) .GroupBy (GPI => gpi.BusDate) .ToDictionary (г => г .Key, g => g.FirstOrDefault(). Balance) ' Я получаю предупреждение о возможной нулевой ссылке в' g.FirstOrDefault() '. Я проверю немного больше и отметю как разрешенное. – skoppisetti

+1

@skoppisetti По сути, вы можете просто использовать 'First', потому что у групп есть как минимум один элемент' g => g.First(). Balance'. – juharr

Смежные вопросы