C# 从对象列表到具有两个属性的字典的优雅方式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/934536/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 03:39:34  来源:igfitidea点击:

Elegant way to go from list of objects to dictionary with two of the properties

c#arraysvisual-studio-2005dictionary

提问by leora

i seem to write this code over and over again and wanted to see if there was a better way of doing it more generically.

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

I start out with a list of Foo objects

我从一个 Foo 对象列表开始

Foo[] foos = GenerateFoos();

I think want to create a dictionary where the key and value are both properties of Foo

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

for example:

例如:

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

is there anyway of writing this code generically as it seems like a basic template where there is an array of objects, a key property a value property and a dictionary.

无论如何,是否可以通用地编写此代码,因为它似乎是一个基本模板,其中有一个对象数组、一个键属性、一个值属性和一个字典。

Any suggestions?

有什么建议?

I am using VS 2005 (C#, 2.0)

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

采纳答案by Marc Gravell

With LINQ:

使用 LINQ:

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

(and yes, fooDictis Dictionary<string, string>)

(是的,fooDictDictionary<string, string>



edit to show the pain in VS2005:

编辑以显示 VS2005 中的痛苦:

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

where you have (in Program):

你在哪里(在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;
}

回答by Guffa

If you are using framework 3.5, you can use the ToDictionaryextension:

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

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

For framework 2.0, the code is pretty much as simple as it can be.

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

You can improve the performance a bit by specifying the capacity for the dictionary when you create it, so that it doesn't have to do any reallocations while you fill it:

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

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

回答by Jonathan Rupp

Without LINQ, no, there's no built-in helpers for this. You could write one though:

没有 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; }));

It doesn't look nearly as elegant as the LINQ-based answers, does it...

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

回答by Paul Suart

Here's a solution that's .net 2.0 compatible that uses System.Web.UI.Databinder to do the reflection on the property name - you lose compile-time type checking.

这是一个与 .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);
    }

You would call as follows:

您将按如下方式调用:

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