C# LINQ 优雅地将 IEnumerable<IGrouping> 转换为 IEnumerable<IEnumerable>?
Posted
技术标签:
【中文标题】C# LINQ 优雅地将 IEnumerable<IGrouping> 转换为 IEnumerable<IEnumerable>?【英文标题】:C# LINQ convert IEnumerable<IGrouping> to IEnumerable<IEnumerable> elegantly? 【发布时间】:2018-03-15 23:39:18 【问题描述】:如果您有IEnumerable<IGrouping<K, T>>
,请说来自
var ans = src.GroupBy(s => s.Field);
有没有更好的方法(很少使用 LINQ 方法/变体)转换为IEnumerable<IEnumerable<T>>
,然后像这样嵌套Select
s:
var ans2 = ans.Select(g => g.Select(s => s));
对于不理解的人,
var anst = ans2.Select(g => g.GetType().ReflectedType).All(t => t == typeof(Enumerable));
应该返回anst == true
。
【问题讨论】:
IGrouping<T>
是什么接口?我只知道IGrouping<K, T>
,已经是IEnumerable<T>
。由于IEnumerable<T>
是协变的,IEnumerable<IGrouping<K, T>>
已经自动成为IEnumerable<IEnumerable<T>>
你到底在问什么?
您的测试与您的问题不匹配...在IEnumerable<IEnumerable> ans2 = Enumerable.Repeat(new List<int>(),1);
ans2 的类型为IEnumerable<IEnumerable>
,但您的测试将返回anst
= false。这是因为 t == typeof(Enumerable)
将返回 true 的唯一类型是 Enumerable
(不是接口,实际类 Enumerable)。这几乎肯定不是你想要的。
这可能是 A/B 问题吗?你想做什么,你觉得你需要做这个转换?正如其他人所说,您已经有了实现IEnumerable<IEnumerable>
的东西。您实际上是否遇到了您认为以上是解决方案的不同问题?
你有一个非常奇怪的要求,所以我不会把这个放在我的答案中,但是看看参考源,如果你可以修改你对 GroupBy 的调用,这将通过你的测试:src.GroupBy( s => s.Field), (key, items) => items.Skip(0));
如果您打算将 GroupEnumerable 转换为 Enumerable,那么您已经有了最巧妙的方法。无需再看其他地方。除非您对该嵌套选择有疑问。
【参考方案1】:
避免嵌套选择的一种解决方案是使用AsEnumerable()
方法。
var ans = src.GroupBy(s => s.Field).Select(e => e.AsEnumerable());
【讨论】:
原来IGrouping<T>.AsEnumerable()
返回IGrouping<T>
。谁知道?
但是 Select
实际上什么也没做。将其关闭会得到相同的结果,因为 IGrouping<T>
是 IEnumerable<T>
。
@NetMage 是的,IGrouping<T>
是 IEnumerable<T>
,因为它实现了IEnumerable<T>
。那你到底想完成什么?如果您最初提出的 IEnumerable<IEnumerable<T>>
不满足您的要求?
我在答案中添加了一个测试。【参考方案2】:
在这种情况下,IGrouping 已经实现了该接口:
public static class Program
static void Main(string[] args)
var foo = new[]
new MyClass a = "1", b = "2",
new MyClass a = "1", b = "3",
new MyClass a = "2", b = "4",
new MyClass a = "2", b = "5" ;
var ans = foo.GroupBy(x => x.a);
IEnumerable<IEnumerable<MyClass>> ans2 = ans;
IEnumerable<IEnumerable<MyClass>> result = ans2.ToArray();
private class MyClass
public string a;
public string b;
【讨论】:
为什么要将结果转换为数组? 原来IGrouping<T>.Cast<IEnumerable<T>>()
返回IGrouping<T>
。
ToArray 将强制枚举 IEnumerable,因此如果出现问题,我会看到抛出异常。在该行之前,任何分组或转换代码实际上都不会做任何工作。
NetMage, CastIEnumerable<IGrouping<K, T>>
已经是IEnumerable<IEnumerable<T>>
。您想要的转换是语言内置的,因此您的要求非常不清楚。你已经得到它了。以上是关于C# LINQ 优雅地将 IEnumerable<IGrouping> 转换为 IEnumerable<IEnumerable>?的主要内容,如果未能解决你的问题,请参考以下文章