迭代中的字典 AddRange 将范围添加到当前和上一个指针
Dictionary AddRange in iteration adds range to both current and previous pointer
我正在根据提供的 Project-2-Groups 和 Group-2-Categories 词典创建 Project-2-Categories 词典。
在我的代码示例中,我期望得到以下结果:
{
"P1": [ "1", "11", "111" ],
"P2": [ "1", "11", "111", "2", "22", "222" ],
}
然而,实际结果是:
{
"P1": [ "1", "11", "111", "2", "22", "222" ],
"P2": [ "1", "11", "111", "2", "22", "222" ],
}
如果能帮我澄清我在这里的误解,我将不胜感激。
Link to fiddle
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var proj2categories = new Dictionary<string, List<string>>();
var proj2groups = new Dictionary<string, List<string>>
{
{ "P1", new List<string>{ "Grp1" } },
{ "P2", new List<string>{ "Grp1", "Grp2" } },
};
var group2categories = new Dictionary<string, List<string>>
{
{ "Grp1", new List<string>{ "1", "11", "111" } },
{ "Grp2", new List<string>{ "2", "22", "222" } },
};
foreach (var p2g in proj2groups)
{
var projKey = p2g.Key;
foreach (var agroup in p2g.Value)
{
if (!group2categories.TryGetValue(agroup, out var categories))
continue;
if (proj2categories.ContainsKey(projKey))
proj2categories[projKey].AddRange(categories);
else
proj2categories.Add(projKey, categories);
}
}
Console.WriteLine("Expected: 3. Actual: " + proj2categories["P1"].Count() + " FAILED");
Console.WriteLine("Expected: 1. Actual: " + proj2categories["P1"].First());
Console.WriteLine("Expected: 111. Actual: " + proj2categories["P1"].Last() + " FAILED");
Console.WriteLine("Expected: 6. Actual: " + proj2categories["P2"].Count());
Console.WriteLine("Expected: 1. Actual: " + proj2categories["P2"].First());
Console.WriteLine("Expected: 222. Actual: " + proj2categories["P2"].Last());
}
}
列表是引用类型。当您第一次分配列表时,您会为 P1 和 P2 分配相同的列表。在此之后将范围添加到 P2 时,实际上是将其添加到现有列表中。这就是为什么你有相同的结果。因此,您已将列表的副本分配给 P1 和 P2,这样您将拥有 2 个独立的列表。在此之后,您可以将范围添加到独立列表 P2.
并且我更改了你的算法以使代码更清晰
foreach (var g2c in group2categories)
foreach (var p2g in proj2groups)
if (p2g.Value.Contains(g2c.Key))
{
var key = p2g.Key;
var val = g2c.Value;
if (!proj2categories.TryGetValue(key, out _))
proj2categories[key] = val.ToList();
else
proj2categories[key].AddRange(val);
}
您可以重复使用相同的列表实例。
但是,每次,您都必须通过 Clear()
清空它,然后再用 out
参数在行中再次填充它,而不是创建新的 List<string>
实例。
我正在根据提供的 Project-2-Groups 和 Group-2-Categories 词典创建 Project-2-Categories 词典。
在我的代码示例中,我期望得到以下结果:
{
"P1": [ "1", "11", "111" ],
"P2": [ "1", "11", "111", "2", "22", "222" ],
}
然而,实际结果是:
{
"P1": [ "1", "11", "111", "2", "22", "222" ],
"P2": [ "1", "11", "111", "2", "22", "222" ],
}
如果能帮我澄清我在这里的误解,我将不胜感激。
Link to fiddle
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var proj2categories = new Dictionary<string, List<string>>();
var proj2groups = new Dictionary<string, List<string>>
{
{ "P1", new List<string>{ "Grp1" } },
{ "P2", new List<string>{ "Grp1", "Grp2" } },
};
var group2categories = new Dictionary<string, List<string>>
{
{ "Grp1", new List<string>{ "1", "11", "111" } },
{ "Grp2", new List<string>{ "2", "22", "222" } },
};
foreach (var p2g in proj2groups)
{
var projKey = p2g.Key;
foreach (var agroup in p2g.Value)
{
if (!group2categories.TryGetValue(agroup, out var categories))
continue;
if (proj2categories.ContainsKey(projKey))
proj2categories[projKey].AddRange(categories);
else
proj2categories.Add(projKey, categories);
}
}
Console.WriteLine("Expected: 3. Actual: " + proj2categories["P1"].Count() + " FAILED");
Console.WriteLine("Expected: 1. Actual: " + proj2categories["P1"].First());
Console.WriteLine("Expected: 111. Actual: " + proj2categories["P1"].Last() + " FAILED");
Console.WriteLine("Expected: 6. Actual: " + proj2categories["P2"].Count());
Console.WriteLine("Expected: 1. Actual: " + proj2categories["P2"].First());
Console.WriteLine("Expected: 222. Actual: " + proj2categories["P2"].Last());
}
}
列表是引用类型。当您第一次分配列表时,您会为 P1 和 P2 分配相同的列表。在此之后将范围添加到 P2 时,实际上是将其添加到现有列表中。这就是为什么你有相同的结果。因此,您已将列表的副本分配给 P1 和 P2,这样您将拥有 2 个独立的列表。在此之后,您可以将范围添加到独立列表 P2.
并且我更改了你的算法以使代码更清晰
foreach (var g2c in group2categories)
foreach (var p2g in proj2groups)
if (p2g.Value.Contains(g2c.Key))
{
var key = p2g.Key;
var val = g2c.Value;
if (!proj2categories.TryGetValue(key, out _))
proj2categories[key] = val.ToList();
else
proj2categories[key].AddRange(val);
}
您可以重复使用相同的列表实例。
但是,每次,您都必须通过 Clear()
清空它,然后再用 out
参数在行中再次填充它,而不是创建新的 List<string>
实例。