如何使用ToDictionary与字典

本文关键字:object 字典 string 何使用 ToDictionary | 更新日期: 2023-09-27 18:12:03

我试图创建一个字典,可以保存每个键的多个值,我已经创建了一个名为Pair的类,它由两个string组成。我已经定义了idDictionary包含一个string作为关键,Pair作为值,但我不确定如何写ToDictionary语句,因为这个概念对我来说是新的,我找不到任何这样的例子。

Dictionary<string, Pair<string, string>> idDictionary = new Dictionary<string, Pair<string, string>>();

我知道对于一个常规的泛型字典,我会简单地使用这样的东西:

idDictionary = resultData.Rows.Select(row => row.Split(','))
                              .ToDictionary(id => id[0], id => id[1]);

我不确定我将如何实现类似的对象称为Pair。也许我遗漏了一些非常简单的东西,但是非常感谢那些给出答案的人。

编辑包括完整的代码块和更彻底的解释

原始代码块在这里(带有泛型字典)。我改变这一点的原因是,如果每个键有超过1个值,应用程序就会因为重复的键而出错。

    private List<ImportItem<T>> ProcessReportResult(CSVTable resultData, ICollection<ImportItem<T>> data, Func<T, string> keyFilter)
    {
        WriteLog("{1}{0} records found.{1}", resultData.Rows.Length, Environment.NewLine);
        //key = Order Number; value = Order ID
        var idDictionary = resultData.Rows.Select((row => row.Split(','))).ToDictionary(id => id[0], id => id[1]);
        idDictionary.ForEach(id => WriteLog("Input Id = {0} - Matching record Id = {1}", id.Key, id.Value));
        var processList = data.Where(item => idDictionary.ContainsKey(keyFilter(item.DataItem))).ToList();
        processList.ForEach(item => item.id = idDictionary[keyFilter(item.DataItem)]);
        return processList;
    }

如何使用ToDictionary与<string, object>字典

获得一对多键值存储的一般解决方案可以通过分组实现,但这需要将value作为项目列表。如果我试图通过给定的示例来解释它,那么将行转换为每键多值存储的查询可以通过以下方式创建:

        idDictionary = 
         resultData.Rows
            .GroupBy(row => row.Id, row => row.Split(','))
            .ToDictionary(g => g.Key, g => g.ToList());
更新:

针对您的问题的具体解决方案。假设数据的结构类似于:

 List<Row> rows = new List<Row>{
            new Row{
                values = "1,A"
            },
            new Row{
                values = "2,C,D,E"
            },
            new DataRow{
                values = "3,E,X,CV,B"
            },
        };

你也可以在这里使用Group来获取Key, Value(List)。注意,这里我跳过了第一个值,它已经在索引0处作为键捕获。

     var idDictionary =
                 rows.GroupBy(row => row.values.Split(',')[0], 
                                  row => row.values.Split(',').Skip(1))
                                 .ToDictionary(g => g.Key, g => g.ToList());

结果如下:

    /* output - 
     |1, (A)|
     |2, (C,D,E)|
     |3, (E,X,CV,B)|
     */

虽然你必须改变通过List获取值的实现。但是,如果在每个键中找到多个值,则此解决方案将阻止程序。

不确定到底需要什么,也许这个简单的例子会有所帮助?

 idDictionary = resultData.Rows
                   .Select((row => row.Split(',')))
                   .ToDictionary<string, Pair<string, string>>
                           (id => id[0],id => new Pair(id[1],id[1]));

这个版本的ToDictionary接受两个函数,一个返回键,另一个返回枚举中每个项的值。

如果您知道每行中有多少项,或者如果您需要考虑每行可能有不同数量的项,则必须决定是否需要基于元组的方法(甚至成对)。

// Setup sample data
var resultData = new
{
    Rows = new string[] { "1,A,B,C", "2,A,B", "3,A,B,C,D" }
};
// If same length for each row, tuple would work easily
// Dictionary<string, Tuple<string, string>>
var tuples = resultData.Rows
    .Select(r => r.Split(','))
    .ToDictionary(
        r => r[0],
        r => Tuple.Create(r[1], r[2])
    );
// If length is variable, then some type of collection could be better
// Dictionary<string, List<string>> 
var lists = resultData.Rows
    .Select(r => r.Split(','))
    .ToDictionary(
        r => r[0],
        r => r.Skip(1).ToList() // Skip adding id element
    );

下面是用于比较的第一项的输出:

?lists["1"]
Count = 3
    [0]: "A"
    [1]: "B"
    [2]: "C"
?tuples["1"]
{(A, B)}
    Item1: "A"
    Item2: "B"

原始代码块在这里(带有泛型字典)。我改变这一点的原因是,如果每个键有超过1个值,应用程序就会因为重复的键而出错。

似乎你正在寻找的是ToLookup

" Lookup<TKey, TElement> 表示映射到一个或多个值的键的集合。"

.

var idDictionary = resultData.Rows.Select((row => row.Split(',')))
                   .ToLookup(id => id[0], id => id[1]);

编辑

简短示例:

var lines = new string[] { "a,b", "a,c", "d,e" };
var dict = lines.Select(line => line.Split(','))
            .ToLookup(x => x[0], x => x[1]);
result: 
    Key: a   Value: [b,c]
    Key: e   Value: [e]
示例用法:

Console.WriteLine(string.Join(",", dict["a"]));