我想使用Linq创建一个函数来总结传入的值序列。该函数应如下所示:
IDictionary<TKey, Summary<TKey>> Summarize<TKey, TValue>(IEnumerable<TValue> values)
{
return values
.ToLookup(val => GetKey(val)) // group values by key
.Union(*an empty grouping*) // make sure there is a default group
.ToDictionary(
group => group.Key,
group => CreateSummary(group)); // summarize each group
}需要注意的是,即使传入的序列不包含具有该键的值,结果IDictionary也应该有一个默认值(TKey)条目。这可以通过纯函数的方式来完成吗?(不使用可变数据结构。)
我能想到的唯一方法就是在查找时调用.Union,然后将其输入到字典中。但这将要求我创建一个空的IGrouping,如果没有显式的类,这似乎是不可能的。有没有一种优雅的方法来做到这一点呢?
编辑:我们可以假设TKey是一个值类型。
发布于 2011-11-09 00:07:19
你不能从GroupBy获取空组,也不能从ToLookup获取。也许这是故意的原因。
这可以用纯函数的方式来完成吗?(不使用可变数据结构。)
虽然这样的学术要求可能很有趣,但任何解决方案都应该与简单直接的实现进行比较。
Dictionary<TKey, Summary<TKey>> result = values
.GroupBy(val => GetKey(val))
.ToDictionary(g => g.Key, g => CreateSummary(g));
TKey x = default(TKey);
if (!result.ContainsKey(x))
{
result[x] = CreateSummary(Enumerable.Empty<TValue>());
}
return result;现在,如果你想要一个空的Group,只需要为它添加一个类:
public class EmptyGroup<TKey, TValue> : IGrouping<TKey, TValue>
{
public TKey Key {get;set;}
public IEnumerator GetEnumerator()
{
return GetEnumerator<TValue>();
}
public IEnumerator<TValue> GetEnumerator<TValue>()
{
return Enumerable.Empty<TValue>().GetEnumerator<TValue>();
}
}如下所示:
EmptyGroup<TKey, TValue> empty = new EmptyGroup<TKey, TValue>(Key = default<TKey>());发布于 2014-01-16 01:33:47
公认的答案就是我想要的,但它对我不起作用。也许我遗漏了什么,但它不能编译。我不得不修改代码来修复它。以下是为我工作的代码:
public class EmptyGroup<TKey, TValue> : IGrouping<TKey, TValue>
{
public TKey Key { get; set; }
public IEnumerator<TValue> GetEnumerator()
{
return Enumerable.Empty<TValue>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}像这样使用
var emptyGroup = new EmptyGroup<Customer, AccountingPaymentClient>();发布于 2011-11-08 14:18:12
您可以添加第二个select,在该select中检查查找表是否有条目,如果没有,则创建一个新的查找表。这与您提议的联合解决方案的不同之处在于,如果存在其他值,则不会添加默认值。
请参见:
IDictionary<TKey, Summary<TKey>> Summarize<TKey, TValue>(IEnumerable<TValue> values)
{
return values
.ToLookup(val => GetKey(val)) // group values by key
.Select(x => x.Any() ? x : Enumerable.Repeat(default(TKey), 1).ToLookup(x => GetKey(x)))
.ToDictionary(
group => group.Key,
group => CreateSummary(group)); // summarize each group
} 如果您需要具有联合的解决方案,则可以使用相同的逻辑来创建默认查找表,如下所示:
IDictionary<TKey, Summary<TKey>> Summarize<TKey, TValue>(IEnumerable<TValue> values)
{
return values
.ToLookup(val => GetKey(val)) // group values by key
.Union(Enumerable.Repeat(default(TKey), 1).ToLookup(x => GetKey(x)))
.ToDictionary(
group => group.Key,
group => CreateSummary(group)); // summarize each group
} 希望这能有所帮助
https://stackoverflow.com/questions/8046425
复制相似问题