我有两个GroupBy的结果:
IEnumerable<IGrouping<long, MyClass>> result1 = ...;
IEnumerable<IGrouping<long, MyClass>> result2 = ...;
我想将它们组合成一个序列。 result2中的某些元素可能具有也是result1中的键的IGrouping键。所以标准Enumerable.Concat
不起作用:
IEnumerable<IGrouping<long, MyClass>> result = result1.Concat(result2);
在结果序列中提到两次具有相同键的项目。显然我需要Concat
IGrouping<TKey, TSource>
这样的特殊public static IEnumerable<IGrouping<TKey, TSource>> Concat<TSource, TKey>
(this IEnumerable<IGrouping<TKey, TSource>> first,
IEnumerable<IGrouping<TKey, TSource>> second)
:
fetch(apiUrl, {
method: method,
headers: headersIfAny,
body: theDataToSend
})
.then(response => /* do something with response */)
.catch(err => /* do something with err */);
我可以取消组合该组的所有元素并再次对它们进行分组,但这当然是浪费。
我看过source code of Enumerable.GroupBy。该方法创建一个GroupedEnumerable对象,该对象将创建一个Lookup对象,就像枚举GroupedEnumerable一样。
我应该做类似的事情,还是有更好的(更容易掌握)方法?
答案 0 :(得分:1)
使用Concat
后跟GroupBy
并使用SelectMany
展平每个结果分组,可以相对轻松地获得所需的结果。
问题是如何将其转换为IGrouping<TKey, TElement>
,因为没有公共标准类实现该接口,它由GroupBy
和ToLookup
实现返回,并且还有没有GroupBy
重载,允许我们需要的东西。所以我们需要自己实现,幸运的是直截了当:
class Grouping<TKey, TElement> : IGrouping<TKey, TElement>
{
IEnumerable<TElement> elements;
public Grouping(TKey key, IEnumerable<TElement> elements)
{
this.Key = key;
this.elements = elements;
}
public TKey Key { get; }
public IEnumerator<TElement> GetEnumerator() => elements.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public static class Grouping
{
public static IGrouping<TKey, TElement> Create<TKey, TElement>(TKey key, IEnumerable<TElement> elements) =>
new Grouping<TKey, TElement>(key, elements);
}
现在有问题的方法的实现可能是这样的:
return first.Concat(second)
.GroupBy(g => g.Key, (key, gg) => Grouping.Create(key, gg.SelectMany(g => g)));