Подтвердить что ты не робот

Возможно ли создать объект IGrouping

У меня List<IGrouping<string,string>>.

Возможно ли добавить новый элемент в этот список? Или, действительно, возможно создать какой-то объект IGrouping?

4b9b3361

Ответ 1

Если вы действительно хотели создать свой собственный IGrouping<TKey, TElement>, это простой интерфейс для реализации:

public class MyGrouping<TKey, TElement> : List<TElement>, IGrouping<TKey, TElement>
{
    public TKey Key
    {
        get;
        set;
    }
}

Этот класс наследует от List<T> и реализует интерфейс IGrouping. Помимо требования быть IEnumerable и IEnumerable<TElement> (который удовлетворяет List<T>), единственным свойством для реализации является Key.

Здесь вы можете создать все MyGrouping<string, string>, которые хотите, и добавить их в свой List<IGrouping<string,string>>.

Ответ 2

Как и в случае с .NET 4.0, в BCL не существует каких-либо публичных типов, которые реализуют интерфейс IGrouping<TKey, TElement>, поэтому вы не сможете с легкостью "обновить".

Конечно, вам ничего не мешает:

  • Создание конкретного типа, который реализует интерфейс, как указывает @Nathan Anderson.
  • Получение экземпляра/экземпляров IGrouping<TKey, TElement> из запроса LINQ, такого как ToLookup и GroupBy, и добавления его/их в список.
  • Вызов ToList() в существующей последовательности групп (из ToLookup/GroupBy).

Пример:

IEnumerable<Foo> foos = ..
var barsByFoo = foos.ToLookup(foo => foo.GetBar());

var listOfGroups = new List<IGrouping<Foo, Bar>>();

listOfGroups.Add(barsByFoo.First()); // a single group
listOfGroups.AddRange(barsByFoo.Take(3)); // multiple groups

Не понятно, почему вы хотели бы это сделать.

Ответ 3

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

var listOfGroups = new[] { "a1", "a2", "b1" }
                       .GroupBy(x => x.Substring(0, 1))
                       .ToList();

// baz is not anything to do with foo or bar yet we group on it
var newGroup = new[] { "foo", "bar" }.GroupBy(x => "baz").Single();

listOfGroups.Add(newGroup);

listOfGroups затем содержит:

a:
    a1, a2
b:
    b1
baz:
    foo, bar

пример IDEOne

Ответ 4

IGrouping<TKey, TElement> CreateGroup<TKey, TElement>(IEnumerable<TElement> theSeqenceToGroup, TKey valueForKey)
{
    return theSeqenceToGroup.GroupBy(stg => valueForKey).FirstOrDefault();
}

Ответ 5

var headers = from header in new[] {
  new { Name = "One", List = new[] { "One 1", "One 2", "One 2" } },
  new { Name = "Two", List = new[] { "Two 1", "Two 2", "Two 2" } }
} from value in header.List group value by header.Name;

Ответ 6

Основываясь на ответе Давида, я создал следующий метод расширения, который создает экземпляр IGrouping<TKey, TElement> из IEnumerable<TElement> и ключ типа TKey:

public static IGrouping<TKey, TElement> ToGroup<TKey, TElement>(
    this IEnumerable<TElement> elements,
    TKey keyValue)
{
    return elements.GroupBy(_ => keyValue).FirstOrDefault();
}

Это можно назвать так:

var fruits = new [] { "Apples", "Bananas" };
var myFruitsGroup = fruits.ToGroup("fruitsKey");

Остерегайтесь того, что ToGroup() может вернуть null.

Я также создал дополнительный метод расширения GroupBy:

public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, IEnumerable<TElement>> elementsSelector)
{
    return source
        .Select(s => elementsSelector(s)
            .ToGroup(keySelector(s)))
        .Where(g => g != default(IGrouping<TKey, TElement>));
}

Его можно использовать так:

var foodItems = new []
{
    new { Category = "Fruits", Items = new [] { "Apples", "Bananas" } },
    new { Category = "Vegetables", Items = new [] { "Tomatoes", "Broccoli" } },
};
var categoryGroups = foodItems.GroupBy(i => i.Category, i => i.Items);

Ответ 7

Интерфейс IGrouping предназначен для оператора GroupBy() в LINQ. Обычно вы получаете объект IGrouping из запроса LINQ с предложением group by. Однако нет смысла иметь список группировок.