是否可以创建一些IGrouping对象

时间:2011-02-22 00:50:02

标签: c# .net collections

我有List<IGrouping<string,string>>

以某种方式可以将新项目添加到此列表中吗?或者实际上,是否可以创建一些IGrouping对象?

7 个答案:

答案 0 :(得分:55)

如果你真的想创建自己的IGrouping<TKey, TElement>,它是一个简单的实现界面:

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

此类继承自List<T>并实现IGrouping接口。除了IEnumerableIEnumerable<TElement>List<T>满足)的要求之外,唯一要实现的属性是Key

从这里,您可以创建所需的所有MyGrouping<string, string>并将其添加到List<IGrouping<string,string>>

答案 1 :(得分:11)

从.NET 4.0开始,BCL中似乎没有任何实现IGrouping<TKey, TElement>接口的 public 类型,因此您将无法“新建一个“很轻松。”

当然,没有什么可以阻止你:

  1. 自己创建一个实现接口的具体类型,正如@Nathan Anderson所指出的那样。
  2. IGrouping<TKey, TElement>ToLookup等LINQ查询中获取GroupBy的实例/实例,并将其添加到您的列表中。
  3. 在现有的一系列群组(来自ToLookup / GroupBy)上调用ToList()
  4. 示例:

    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
    

    但是,为什么你想要做到这一点并不清楚。

答案 2 :(得分:5)

您还可以通过不对列表中的内容进行分组来破解分组:

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 example

答案 3 :(得分:5)

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

答案 4 :(得分:1)

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;

答案 5 :(得分:1)

基于dovid的回答,我创建了以下扩展方法,该方法从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);

答案 6 :(得分:-2)

IGrouping接口用于LINQ中的GroupBy()运算符。您通常会从带有 IGrouping 子句的LINQ查询中获取group by对象。但是,拥有一个分组列表没有多大意义。