C# Linq - Добавить нулевые значения и номера недель в список, если они отсутствуют - PullRequest
0 голосов
/ 09 апреля 2020

Мне удалось использовать Группировать список по категориям и WeekNumber без проблем. Проблема, с которой я сталкиваюсь, заключается в том, как добавить 0 и заполнить пропущенные значения WeekNumber. Если бы у меня просто были «Автомобили», то было бы неплохо и легко, но я не могу правильно использовать Distinct () для итерации по каждой категории.

Текущий список:

Current List

Ожидаемый результат:

Expected Result

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

for (var i = 1; i <= 52; ++i)
{
   if (vehicleSales.Count(x => x.x == i) == 0)
   {
      vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = "Cars" });
   }
}

Помощь и советы приветствуются!

Ответы [ 2 ]

1 голос
/ 09 апреля 2020

Ваш пример кода может стать медленным, так как вы перебираете все записи с помощью '.Count (x => xx == i)') 52 раза (когда у вас миллионы записей, это снежки, всего с несколькими записями вы будете не замечайте много).

Что вы можете сделать, это сохранить данные в словаре:

salesBreakdownByCategory = new Dictionary<String, int[]>();

, тогда вы один раз go для всех ваших записей один раз:

foreach(var breakdown in vehicleSales)
{
    int[] values;
    if(!salesBreakdownByCategory.TryGetValue(vehicleSales.Category, out values))
    {
        values = new int[52]; // every entry in the array is by default 0 
        salesBreakdownByCategory[vehicleSales.Category] = values;
    }
    values[vehicleSales.WeekNumber-1] = vehicleSales.Value;
}

таким образом, у вас есть все данные, хранящиеся в массиве, но если вы хотите иметь список, вам нужно снова запустить структуру данных:

var result = salesBreakdownByCategory.SelectMany(x=>x.Select( (value,index) => new WeeklySalesBreakdown { WeekNumber = index+1, Value = value, Category = x.Key}));

Когда вы хотите избежать дополнительных выделение памяти и добавление данных в существующий список, вместо сохранения значения в массиве int, как в примере выше, вы можете вместо этого использовать массив bool и установить значение true для каждой найденной записи. Затем вам просто нужно перебрать словарь снова и добавить запись в ваш исходный список всякий раз, когда для bool не было установлено значение true

0 голосов
/ 09 апреля 2020

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

var categories = vehicleSales.Select(v => v.Category).Distinct().ToList();
foreach(var category in categories)
{
    for (var i = 1; i <= 52; ++i)
    {
        if (!vehicleSales.Any(x => x.Category == category && x.WeekNumber == i))
        {
            vehicleSales.Add(new WeeklySalesBreakdown { WeekNumber = i, Value = 0, Category = category });
        }
    }
}
...