Dictionary ForAll / ForEach方法

时间:2016-02-22 15:06:18

标签: c# .net linq dictionary iteration

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,而不是你想要实现的目标。

我要感谢大家的评论和答案,我今天学到了很多东西。

3 个答案:

答案 0 :(得分:3)

对于您要创建的每个KeyValuePair<string,string>,并返回具有适当属性的新XElement。这称为投影

SelectLINQ的投影方法:<​​/ 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可能是更好的选择。