Как работать с отдельными элементами по индексу в группе в IGrouping?

Я упростил групповой код ниже, где я знаю, что существует не более двух записей для каждой группы, причем каждая группа сгруппирована по значению в индексе два в строке массива. Я хочу перебрать список ключей в IGrouping и объединить некоторые значения в каждой группе, а затем добавить этот результат в окончательный список, но я новичок в LINQ, поэтому точно не знаю, как получить доступ к этим первым и/или вторым значения по индексу.

Может ли кто-нибудь пролить свет на то, как это сделать?

каждая группа, полученная из строк var, выглядит примерно так:

 key    string[]
----   ------------- 
123    A, stuff, stuff
123    B, stuff, stuff

и я хочу, чтобы результатом была строка [], которая объединяет элементы каждой группы в «финальном» списке, например:

string[]
-------
A, B

мой код:

     var lines = File.ReadAllLines(@path).Skip(1).Select(r => r.Split('\t')).ToList();
     List<string[]> final = new List<string[]>();
     var groups = lines.GroupBy(r => r[2]);

     foreach (var pairs in groups)
     {
        // I need to combine items in each group here; maybe a for() statement would be better so I can peek ahead??
        foreach (string[] item in pairs)
        {
           string[] s = new string[] { };
           s[0] = item[0];
           s[1] = second item in group - not sure what to do here or if I am going aboout this the right way

           final.Add(s);
        }
     }

По этому вопросу тоже не слишком много поддержки, поэтому я подумал, что это может быть кому-то полезно.


person kmk09k    schedule 06.07.2015    source источник


Ответы (1)


Похоже, все, что вам не хватает, это позвонить ToList или ToArray в группу:

foreach (var group in groups)
{
    List<string[]> pairs = group.ToList();
    // Now you can access pairs[0] for the first item in the group,
    // pairs[1] for the second item, pairs.Count to check how many
    // items there are, or whatever.
}

Или вы можете не создавать список и вызывать Count(), ElementAt(), ElementAtOrDefault() и т. д. в группе.

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

var final = lines.GroupBy(r => r[2])
                 .Select(g => ...)
                 .ToList()

где ... — это «все, что вы хотите сделать с группой». Если бы вы могли это сделать, это сделало бы код намного яснее.

С дополнительной информацией в вопросе похоже, что вы хотите просто:

var final = lines.GroupBy(r => r[2])
                 .Select(g => g.Select(array => array[0]).ToArray())
                 .ToList()
person Jon Skeet    schedule 06.07.2015
comment
Я попробовал ваше точное второе решение перед публикацией, но я не знал, как получить доступ к первому и второму результатам для каждого ключа с помощью LINQ, отсюда и запутанные циклы foreach. - person kmk09k; 06.07.2015
comment
@ kmk09k: Теперь, когда вы предоставили больше информации, это довольно просто - если вы просто хотите, чтобы первый элемент из каждого string[] в вашей группе, это простой Select с ToArray в конце. Я отредактирую свой ответ. - person Jon Skeet; 06.07.2015
comment
спасибо - ваше отредактированное второе решение сработало для меня. На самом деле мне нужно написать немного больше логики для объединения моих сгруппированных элементов, чем в моем примере, поэтому я просто сделал var final = lines.GroupBy(r => r[2]).Select(g => g.Select(a = › a).ToArray()).ToList() и работал со списком. Результат был мгновенным, поэтому я не жалуюсь. - person kmk09k; 07.07.2015