【问题标题】:Elegant way to go from list of objects to dictionary with two of the properties从对象列表到具有两个属性的字典的优雅方式
【发布时间】:2010-10-30 09:22:21
【问题描述】:

我似乎一遍又一遍地编写这段代码,想看看是否有更好的方法更通用。

我从一个 Foo 对象列表开始

Foo[] foos = GenerateFoos();

我想创建一个字典,其中键和值都是 Foo 的属性

例如:

Dictionary<string, string> fooDict = new Dictionary<string, string>():
foreach (Foo foo in foos)
{
    fooDict[foo.Name] = foo.StreetAddress;
}

是否可以通用地编写这段代码,因为它看起来像是一个基本模板,其中有一个对象数组、一个键属性、一个值属性和一个字典。

有什么建议吗?

我正在使用 VS 2005 (C#, 2.0)

【问题讨论】:

    标签: c# arrays visual-studio-2005 dictionary


    【解决方案1】:

    使用 LINQ:

    var fooDict = foos.ToDictionary(x=>x.Name,x=>x.StreetAddress);
    

    (是的,fooDictDictionary&lt;string, string&gt;


    编辑以显示 VS2005 中的痛苦:

    Dictionary<string, string> fooDict =
        Program.ToDictionary<Foo, string, string>(foos,
            delegate(Foo foo) { return foo.Name; },
            delegate(Foo foo) { return foo.StreetAddress; });
    

    你在哪里(Program):

    public static Dictionary<TKey, TValue> ToDictionary<TSource, TKey, TValue>(
        IEnumerable<TSource> items,
        Converter<TSource, TKey> keySelector,
        Converter<TSource, TValue> valueSelector)
    {
        Dictionary<TKey, TValue> result = new Dictionary<TKey, TValue>();
        foreach (TSource item in items)
        {
            result.Add(keySelector(item), valueSelector(item));
        }
        return result;
    }
    

    【讨论】:

    • 嗯,您可以使用匿名方法和实用程序类编写类似的东西,但它可能比您现有的代码工作更多......
    • 哦,太好了。比我的好多了:(
    • 伙计,这个语法很漂亮。我无法想象编译器是如何完成所有这些工作的——我知道它做了很多工作。我的意思是,智能感知也是!
    • 既然知道item的个数,不妨设置字典的初始容量:new Dictionary&lt;TKey, TValue&gt;(items.Count())
    【解决方案2】:

    如果您使用的是 framework 3.5,则可以使用 ToDictionary 扩展名:

    Dictionary<string, string> fooDict = foos.ToDictionary(f => f.Name, f => f.StreetAddress);
    

    对于框架 2.0,代码非常简单。

    您可以通过在创建字典时指定字典的容量来稍微提高性能,这样它就不必在填充时进行任何重新分配:

    Dictionary<string, string> fooDict = new Dictionary<string, string>(foos.Count):
    

    【讨论】:

      【解决方案3】:

      没有 LINQ,不,没有内置的帮助程序。你可以写一个:

      // I forget if you need this delegate definition -- this may be already defined in .NET 2.0
      public delegate R Func<T,R>(T obj);
      public static Dictionary<K,V> BuildDictionary<T,K,V>(IEnumerable<T> objs, Func<T,K> kf, Func<T,V> vf)
      {
          Dictionary<K,V> d = new Dictionary<K,V>();
          foreach (T obj in objs)
          {
              d[kf(obj)] = vf(obj);
          }
          return d;
      }
      
      Dictionary<string, string> fooDict = BuildDictionary(foos, new Func<Foo,string>(delegate(Foo foo) { return foo.Name; }), new Func<Foo,string>(delegate(Foo foo) { return foo.StreetAddress; }));
      

      它看起来不像基于 LINQ 的答案那么优雅,是吗...

      【讨论】:

      • 我需要检查一下,但您可能会发现您需要指定泛型类型...泛型类型推断在 C# 3.0 中变得更强大(在 C# 2.0/ 中并不是那么好) VS2005)
      • 我很确定泛型类型推断在 2.0 中,但委托推断不是——如果是,你可以删除“new Func”的东西。
      • 当然,我似乎总是忘记这些东西在 2.0 中是什么——我只是让编译器的抱怨成为我的记忆设备:)
      • 啊,是的;我们都对!使用新的 Func,泛型类型推断很高兴;但如果没有(即仅委托 {...}),您需要指定泛型类型;-p
      【解决方案4】:

      这是一个与 .net 2.0 兼容的解决方案,它使用 System.Web.UI.Databinder 对属性名称进行反射 - 您会丢失编译时类型检查。

              public static Dictionary<string, string> ToDictionary<T>(List<T> list, string keyName, string valueName)
          {
              Dictionary<string, string> outputDictionary = new Dictionary<string, string>();
              foreach (T item in list)
              {
                  string key = Eval<T, string>(item, keyName);
                  string value = Eval<T, string>(item, valueName);
                  output[key] = value;
              }
      
              return outputDictionary;
          }
      
          public static TOut Eval<TIn, TOut>(TIn source, string propertyName)
          {
              object o = DataBinder.GetPropertyValue(source, propertyName);
              if (o is TOut)
                  return (TOut)o;
      
              return default(TOut);
          }
      

      你会这样调用:

      Dictionary<string, string> fooDict = ToDictionary(foos, "Name", "StreetAddress");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-08-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-01
        • 2020-06-18
        • 2018-07-02
        相关资源
        最近更新 更多