【问题标题】:Change the value of an embedded dictionary in C#在 C# 中更改嵌入字典的值
【发布时间】:2020-10-14 12:42:00
【问题描述】:

我有一本这样的字典:

public Dictionary<string, Dictionary<List<string>, bool>> dictionary= new Dictionary<string, Dictionary<List<string>, bool>>();

这个字典被布尔值填充,默认为 false。

我想将特定行(在嵌入字典中)中的布尔值更改为 true;变成这样。

  dictionary["cell-22"] = {"cell-22", {["first property", "second property"]}, true}

 

【问题讨论】:

  • Dictionary 键使用List&lt;string&gt; 没有多大意义,因为它将根据List 的引用而不是列表中的值进行散列,除非您还创建IEqualityComparer 为您执行此操作并在您创建字典时传递 tn。
  • 如果您需要一个恰好包含 2 个字符串值的键,您可以改为使用 Dictionary&lt;(string, string), bool&gt;Dictionary&lt;Tuple&lt;string, string&gt;, bool&gt;
  • 这是XY problem。这本词典似乎非常非常错误。它应该做什么和如何使用?
  • Lists 是引用对象,这意味着相等性只会对相同的对象实例起作用,因此它不会像您期望的那样起作用。
  • 对于像public class GridCell { public Dictionary&lt;string, bool&gt; properties = new Dictionary&lt;string, bool&gt;(); } 然后public GridCell[,] grid = new GridCell[width, height]; 这样的网格不会更好吗?

标签: c# dictionary unity3d


【解决方案1】:

您可以使用字典,但不能使用List&lt;string&gt;!您总是需要完全相同的列表引用才能从Dictionary 访问相应的元素。

而让内部的只是一个Dictionary&lt;string, bool&gt; 用于将一个键映射到一个值


出于可读性和可维护性的原因,而不是嵌套这些集合类型,我宁愿创建适当的包装类,例如

public class GridCell 
{ 
    public Dictionary<string, bool> Properties = new Dictionary<string, bool>(); 
}
 

然后由于您提到了网格而不是通过字符串键访问某些字段,我宁愿在实际的“网格”或二维数组中使用它

public GridCell[,] Grid = new GridCell[width, height];
public List<string> GridProperties = new List<string>();

为了初始化它,你会运行一次,例如

for(var i = 0; i < width; i++)
{
    for(var j = 0; j < height; j++)
    {
        var newGridCell = new GridCell();
        foreach(var property in GridProperties)
        {
            newGridCell.properties.Add(property, false);
        }
        Grid[i, j] = newGridCell;
    }
}

然后您可以访问任何属性,例如

var hasProperty = Grid[2,2].Properties[propertyName];

Grid[2,2].Properties[propertyName] = true;

为了一次设置多个属性而实现一个类似的方法

public class GridCell 
{ 
    public Dictionary<string, bool> Properties = new Dictionary<string, bool>(); 

    public void SetProperties(List<string> properties, bool value)
    {
        foreach(var property in properties)
        {
            // Either updates the entry if it exists already
            // or adds a new entry for this key
            Properties[property] = value;
        }
    }
}

然后在网格类中去

public void SetProperties(int gridX, int gridY, List<string> properties, bool value)
{
    // creates the new field if it didn't exist so far
    if(Grid[gridX, gridX] == null)) Grid[gridX, gridY] = new GridCell();

    Grid[gridX, gridY].SetProperties(properties, value);
}

当然,你仍然可以只使用字典来做同样的事情,就像在内部字典之前一样使用List&lt;string&gt;但只有string作为键

public Dictionary<string, Dictionary<string, bool>> Grid = new Dictionary<string, Dictionary<string, bool>>();

然后在相应地初始化它之后,您可以访问一个特定的值,例如

var hasProperty = Grid[indexName][propertyName];

Grid[indexName][propertyName] = true;

为了一次设置多个值,您应该实现自己的方法,例如

public void SetProperties(string indexName, List<string> properties, bool value)
{
    // creates the new field if it didn't exist so far
    if(!Grid.ContainsKey(indexName)) Grid[indexName] = new Dictionary<string, bool>();

    foreach(var property in properties)
    {
        // This either updates an existing property entry
        // or creates a new one if it didn't exist so far
        Grid[indexName][property] = value;
    }
}

我更喜欢顶部的解决方案以获得更好的可维护性。您可以轻松地在GridCell 类中实现更多方法,或者更改和扩展现有方法,而不会过多影响外部的任何内容。您还可以轻松地将与网格相关的内容分离(解耦)到一个额外的类中,而无需例如使用太多方法使MonoBehaviour 组件混乱。

使用第二种方法,您将终止于一个超级强大的类,该类在这个嵌套的Dictionary 内完成所有工作。

【讨论】:

    【解决方案2】:

    您的字典定义可能是正确的(如果没有更好的问题澄清,这不太可能但很难明确地说出来)。

    public Dictionary<string, Dictionary<List<string>, bool>> dictionary= new Dictionary<string, Dictionary<List<string>, bool>>();
    

    在第二个字典中有一个键看起来不太可能。 我怀疑这就是你的意思。

    public Dictionary<string, List<(string, bool)> dictionary= new Dictionary<string,List<(string, bool)>();
    

    【讨论】:

    • Dictionary&lt;string, List, bool&gt; 更没有意义,因为字典只有键和值的泛型类型,没有第三种泛型类型。
    • 我还在编辑你们快点评论 ;)
    • 在您正确格式化您的答案之前不要发布,否则会发生类似的事情;)(我删除了我的反对票,现在它是有道理的)
    • 这只是网络的本质,如果你完全制定你的答案并得到正确的答案(就像我以前做的那样),那么接受的答案会在你写完大部分内容之前发布 10 分钟时间。我只是把一个答案放在一起,以获得我需要能够发表评论的几点,这样我就可以帮助人们而不是为了声誉积分而参加激烈的比赛
    猜你喜欢
    • 2022-06-13
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 2018-05-23
    • 2012-09-16
    • 2016-01-11
    相关资源
    最近更新 更多