如何使用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;
}
获得一对多键值存储的一般解决方案可以通过分组实现,但这需要将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"]));