Dictionary ForAll / ForEach方法
什么是Dictionary
对象的正确的ForAll
方法? 我正在学习Linq类型的迭代(下面的方法1),但没有得到它的工作。 旧的foreach
循环有效(下面的方法2)。 尽管在类似问题上有很多答案,例如这个问题,但我没有看到Linq迭代解决方案。
该词典似乎有方法来获取所有的键或所有值,在Linq迭代中可用,但不能获得所有KeyValuePairs。 奇怪!
我做了一些GetEnumeration()
,但没有多少运气。
AsParallel()
方法似乎是解决方案,在这里找到,但对我来说,我只有一个构建错误:字典不包含AsParallel的定义。
有人可能会说方法2没有太多的源代码,但对我来说,方法1的Linq迭代更简单,更直接,更优雅。
还有一种简单的方法可以使方法1工作吗?
版本:.Net Framework 4.5.2
using System.Linq;//AsParallel, ToList
using System.Collections.Generic;//Dictionary
using System.Xml.Linq;//XElement
using System.IO;//Path, Dir, File
public Dictionary<string, string> DictUserConfig = new Dictionary<string, string>();
public void SaveFile(string FileName)
{
XDocument XDConf = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));
#if true//method 1: problem: Dictionary does not have a .ForAll or .ForEach method, or .GetEnumerator().ForAll(x => ...)
XDConf.Add(
new XElement("settings",
DictUserConfig.ForEach(x =>
new XElement("add",
new XAttribute("key", x.Key),
new XAttribute("value", x.Value)))));
#else//method 2: works
XElement XSettings = new XElement("settings");
XDConf.Add(XSettings);
foreach (KeyValuePair<string, string> x in DictUserConfig)
{
XSettings.Add(
new XElement("add",
new XAttribute("key", x.Key),
new XAttribute("value", x.Value)));
}
#endif
XDConf.Save(FileName);
return;
}
更新:我发现了一个问题:缺少using System.Linq
,前一段时间删除时,我不需要。 通过在我的帖子上测试几条有用的评论来发现。
现在这个问题更容易总结为:
这工作:
DictUserConfig.ToList<KeyValuePair<string, string>>().ForEach(x => Console.WriteLine(x.Key + x.Value));
DictUserConfig.AsParallel().ForAll(x => Console.WriteLine(x.Key + x.Value));
但是这不起作用:
XElement XE1 = (XElement)DictUserConfig.ToList<KeyValuePair<string, string>>().ForEach(x => new XElement(x.Key, x.Value));
XElement XE2 = DictUserConfig.AsParallel().ForEach(x => new XElement(x.Key, x.Value));
原因是,我想,ToList和AsParallel不会将ForEach的结果返回给this
。 构建错误是:无法将void转换为对象(或XElement)。 所以唯一的'解决方案'似乎使用单线程创建ForEach,这已经显示为一个解决方案,但要小心返回一个XElement对象。
在测试了最终答案后,我想指出的是,讨论不是关于ForEach与foreach的相对值,而是这掩盖了Select的真实解决方案。 此外,foreach更是Fortran制造事情的方式,ForEach,特别是Select,而不是你想要达到的目标。
我想感谢大家的评论和答复,我今天学到了一些东西。
对于每个KeyValuePair<string,string>
您要创建并返回具有适当属性的新XElement
。 这被称为投影 。
Select
是LINQ
的投影方法:
XDConf.Add(new XElement("settings",
DictUserConfig.Select(
kvp => new XElement("add",
new XAttribute("key", kvp.Key),
new XAttribute("value", kvp.Value)))/*.
Cast<object>().ToArray()*/));
最后的转换是调用XElement
的正确构造函数所必需的。
请注意, List<T>.ForEach
遍历枚举并为每个KeyValuePair
调用一个Action<KeyValuePair<TKey,TValue>>
。 但它不会返回任何内容,因此您不能在XElement
构造函数调用中使用它。
您可以使用ToList扩展方法来获取与ForEach方法兼容的KeyValuePairs列表。
Dictionary<string, int> testDict = new Dictionary<string, int>();
testDict.Add("one", 1);
testDict.Add("two", 2);
testDict.Add("three", 3);
testDict.ToList<KeyValuePair<string, int>>().ForEach(x => Console.WriteLine(x.Key));
DotNetFiddle在这里:https://dotnetfiddle.net/5rRGZc
不过,我同意Sakura的评论,即正常的foreach可能是更好的选择。
ForEach()
是List<T>
类的一种特定方法。
但是你可以制作你自己的Dictionary<TKey, TVakue>
方法:
public static class DictionaryExtensions
{
public static void ForEach<TKey, TValue>(this Dictionary<TKey, TValue> dict, Action<KeyValuePair<TKey, TValue>> action)
{
foreach (var item in dict)
action(item);
}
}
然后像这样使用它:
XElement XSettings = new XElement("settings");
DictUserConfig.ForEach(x =>
XSettings.Add(new XElement("add",
new XAttribute("key", (string)x.Key),
new XAttribute("value", (string)x.Value))));
更新 :
使用方法1,那么你可以使用这样的扩展器:
public static IEnumerable<TResult> ForEach<TKey, TValue, TResult>(this Dictionary<TKey, TValue> dict, Func<KeyValuePair<TKey, TValue>, TResult> func)
{
foreach (var item in dict)
yield return func(item);
}
那么方法1将是:
XDConf.Add(new XElement("settings",
DictUserConfig.ForEach(x =>
new XElement("add", new XAttribute("key", x.Key),
new XAttribute("value", x.Value))).ToArray()));
在ToArray()
之前可能需要Cast<object>()
ToArray()
。