我正在尝试迭代一个简单的异构容器:Dictionary<string, object>
.
它是这样构造的:
var d = new Dictionary<string, object>();
d.Add("key1", "value1");
d.Add("key2", 42);
var sub = new Dictionary<string, object>();
sub.Add("key3", new double[] { 0, 0 });
d.Add("key4", sub);
我假设我可以写一个简单的函数:
public IEnumerable<KeyValuePair<string, object>> flatten(IDictionary<string, object> dict)
{
foreach(KeyValuePair<string, object> item in dict)
{
if (item.Value is IDictionary<string, object> subDict)
{
flatten(subDict);
}
else
{
yield return item;
}
}
}
我如何重写上面的flatten
函数,使:
var l = flatten(d).ToList();
返回一个包含三个项目的列表(键为:key1、key2和key3)。我还没有能够使用SelectMany
从Linq包在我的情况下到目前为止…
Try yield returnflatten
递归调用的结果:
public IEnumerable<KeyValuePair<string, object>> flatten(IDictionary<string, object> dict)
{
foreach (KeyValuePair<string, object> item in dict)
{
if (item.Value is IDictionary<string, object> subDict)
{
foreach (var item2 in flatten(subDict))
{
yield return item2;
}
}
else
{
yield return item;
}
}
}
如果您想使用SelectMany
,您实际上需要将非IDictionary<...>
投影到IEnumerable
(因此dict
是总是被认为是要扁平的集合的集合):
public IEnumerable<KeyValuePair<string, object>> flatten(IDictionary<string, object> dict)
{
return dict.SelectMany(kv => kv.Value switch {
IDictionary<string, object> subdict => flatten(subdict),
_ => Enumerable.Repeat(kv, 1)
});
}
现场演示
我们不需要说yield return
因为SelectMany
会直接返回IEnumerable