c # Linq или код для извлечения групп из единого списка исходных данных

#c# #algorithm #list #linq

#c# #алгоритм #Список #linq

Вопрос:

У меня есть данные в списке, поступающие из сторонней библиотеки dll. Я не могу изменить способ поступления данных. Этот список является непрерывным и непрерывным без разделителей

 List<MyType> DataList
  

Каждой строке соответствует порядковый номер. Номера индексов могут быть от 1 до 4, максимальное число 4. Таким образом, в оптимальном варианте мы бы увидели группы строк, пронумерованные от 1 до 4, одну группу за другой. Но в группах может отсутствовать порядковый номер.

Как вы можете видеть здесь, первая группа содержит 1-4, вторая группа — 1,2,4 (отсутствует 3), а третья группа — 1,2,3 (отсутствует 4), а также строки могут быть вставлены таким образом, чтобы индексы располагались не в любом порядке

Пробелы в строках, которые вы видите здесь, я вставил только для наглядности

     Filename    Index   Time                
    File_1      1       42038.6924500000    
    File_2      2       42038.6435300000    
    File_3      3       42038.7962800000    
    File_4      4       42038.9340600000    

    File_5      2       42938.9561300000    
    File_6      1       42939.0110700000    
    File_7      4       42939.5551700000    

    File_8      2       43838.9652200000    
    File_9      1       43839.0111500000    
    File_10     3       43839.0990100000    
  

Мне нужно извлечь из этого списка 4 отдельные группы на основе номера индекса. Таким образом, каждая группа составляется либо из всего индекса 1, либо из всего индекса 2 и т.д.
но там, где отсутствует номер индекса, мне нужно вставить разделительную строку для заполнения, чтобы указать отсутствующий индекс.

НАПРИМЕР, приведенное выше должно заканчиваться следующим образом

 group on index 1
File_1      1       42038.6924500000    
File_6      1       42939.0110700000  
File_9      1       43839.0111500000    

group 2 on index 2
File_2      2       42038.6435300000    
File_5      2       42938.9561300000 
File_8      2       43838.9652200000    

group 3 on index 3
File_3      3       42038.7962800000    
File_spacer 3       00000.0000000000
File_10     3       43839.0990100000   

group 4 on index 4
File_4      4       42038.9340600000
File_7      4       42939.5551700000 
File_spacer 4       00000.0000000000
  

Итак, я мог бы сделать Linq

 DataList.GroupBy(x => X.Index)).ToList()
  

но при этом не будет вставлена запись File_spacer с индексом 0000.000000000, которая мне нужна, чтобы заменить отсутствующий индекс в качестве заполнителя.

Обычно список может содержать 500 строк данных таким образом, но я не могу придумать код на C # для извлечения и форматирования, как мне нужно.

Любые предложения приветствуются

Комментарии:

1. После того, как вы сгруппируете, выполните цикл по каждой группе и посмотрите, меньше ли количество в группе числа x, и добавьте разделитель.

2. Поскольку кажется, что индексы могут отображаться в любой позиции, как вы решили, что в группе 3 заменитель индекса 3 займет 2-ю позицию, в то время как в группе 4 он окажется на последней позиции?

3. @jimi потому что во второй «группировке» чисел отсутствует индекс 3 (как представлено мной с интервалом для наглядности). в третьей группе отсутствует индекс 4, поэтому разделитель для индекса номер 4 находится на третьей позиции. идея с интервалом заключается в сохранении позиционной четности от группы к группе.

Ответ №1:

Попробуйте следующее:

 double tickPerDay = (double)(24.0 * 60.0 * 60.0 * 10000000.0);
List<MyType> DataList = new List<MyType>() {
    new MyType() { Filename = "File_1", Index = 1, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .6924500000))},
    new MyType() { Filename = "File_2", Index = 2, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .6435300000))},
    new MyType() { Filename = "File_3", Index = 3, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .7962800000))},
    new MyType() { Filename = "File_4", Index = 4, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .9340600000))},
    new MyType() { Filename = "File_5", Index = 2, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .9561300000))},
    new MyType() { Filename = "File_6", Index = 1, Time = (DateTime.Parse("1/1/1900").AddDays(42039)).AddTicks((long)(tickPerDay * .9561300000))},
    new MyType() { Filename = "File_7", Index = 4, Time = (DateTime.Parse("1/1/1900").AddDays(42039)).AddTicks((long)(tickPerDay * .5551700000))},
    new MyType() { Filename = "File_8", Index = 2, Time = (DateTime.Parse("1/1/1900").AddDays(42038)).AddTicks((long)(tickPerDay * .9652200000))},
    new MyType() { Filename = "File_9", Index = 1, Time = (DateTime.Parse("1/1/1900").AddDays(42039)).AddTicks((long)(tickPerDay * .0111500000))},
    new MyType() { Filename = "File_10", Index = 3, Time = (DateTime.Parse("1/1/1900").AddDays(42039)).AddTicks((long)(tickPerDay * .0990100000))}
    };

int maxIndex = DataList.Max(x => x.Index);

var results = DataList.GroupBy(x => x.Index)
    .Select(x => Enumerable.Range(1, maxIndex)
        .Select(y => x.Any(z => z.Index == y) ? x.Where(z => z.Index == y).FirstOrDefault() : new MyType() { Filename = "File_spacer", Index = y, Time = DateTime.Parse("1/1/1900")})
        .ToList())
    .ToList();  
  

Комментарии:

1. System.TimeSpan.TicksPerDay .