ForAll
对象的正确Dictionary
方法是什么?我正在学习Linq类型的迭代(下面的方法1),但是没有让它工作。旧foreach
循环有效(下面的方法2)。尽管在类似问题上有许多答案,例如this question,我没有看到Linq迭代解决方案。
字典似乎有方法可以获取在Linq迭代中可用的所有键或所有值,但不能获取所有KeyValuePairs。奇怪!
我做了一些摆弄GetEnumeration()
但没有太多运气。
AsParallel()
方法似乎是解决方案,找到here,但对我来说,我只有一个构建错误:字典不包含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转换为object(或XElement)。因此,唯一的“解决方案”似乎是使用单线程创建ForEach,这已经显示为解决方案,但要注意返回XElement对象。
在测试完最终答案之后,我想指出,讨论不是关于ForEach与foreach的相对值,而是这模糊了Select的真正解决方案。此外,foreach更多是Fortran制作事物的方式,ForEach,尤其是Select,而不是你想要实现的目标。
我要感谢大家的评论和答案,我今天学到了很多东西。
答案 0 :(得分:3)
对于您要创建的每个KeyValuePair<string,string>
,并返回具有适当属性的新XElement
。这称为投影。
Select
是LINQ
的投影方法:</ p>
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
会对枚举进行迭代,并为每个Action<KeyValuePair<TKey,TValue>>
调用KeyValuePair
。但它不会返回任何内容,因此您无法在XElement
构造函数调用中使用它。
答案 1 :(得分:1)
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()));
Cast<object>()
之前可能需要ToArray()
。
答案 2 :(得分:1)
您可以使用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可能是更好的选择。