是否可以为每个密钥设置多个值而无需先查找密钥?

时间:2014-01-14 14:14:32

标签: c# .net dictionary

我正在编写一个2D无限地形编辑器,专注于性能。每次用户绘制时,他都会创建Node,此时此类被分配给“图层”类中的词典。由于用户可以在不同的图层上绘制现有节点,我想找到这些节点并销毁它们。使用我当前的设置,这将涉及循环遍历所有图层并从字典中逐个获取必要的节点

显然,如果每帧完成数万次,这太昂贵了。所以现在我想我可以创建一个包含列表中所有节点的字典。然而,事实证明使用的功能几乎与之前的设置一样多,因为现在我必须在实例化新节点时检查密钥是否已经存在:

之前:

public Node(){
  dic.Add(key,this);
}

现在:

public Node(){
  List<Node> nodes;
  if(dic.TryGetValue(key,out nodes))
    nodes.Add(this);
  else{
    list = new List<Node>();
    dic.Add(key,list);
  }
}

正如您所看到的,虽然当前设置在检查节点时节省了一些性能,但它通过字典查找时间膨胀实例化时间完全破坏了效果。

所以现在我正在寻找一些方法来获得与Dictionary<Key,List<Node>>相同的效果,但不需要在字典中查找列表的成本。是否有一种不同类型的字典可以让每个字符串无限(或必要时有限)数量的每个键值?

或者,是否有可能以某种方式对字典中的值进行排序,这样我就可以使用普通Dictionary<key, Node>,然后查找第一个键并从那里循环遍历所有值,直到我点击某个节点不再符合搜索条件?

在伪代码中,我的实例化函数如下所示:

public Node(){
  dic.Add(key+LayerIndex,this);
}

我的查找功能看起来像这样

public LookUpAll(key, out list){
  var o = dic[key]; // looking up just one node
  list.Add(o);
  var keyPosition = o.keyPosition;
  while(o.position == keyPosition){ // then looping through all other nodes at that position until one comes that has a different position.
    o = dic.NextValue();
    list.Add(o);
  }
}

现在,这在未排序的词典上不起作用,但是因为我希望这里的某个人可以从中得到一些灵感并制定出有效的解决方案。

如何在我的方案中减少查找次数,或者在不先查找密钥的情况下为每个密钥添加多个值?

2 个答案:

答案 0 :(得分:1)

  

由于用户可以在现有节点上进行绘制,因为他处于不同的状态   层,

我将假设这样做不会导致持久存储您不需要的数据。但是如果用户不打算删除该层上的数据呢?他只是想“看到”某些东西看起来如何。然后他撤消了他的改变和blammo,你没有关于他刚刚做的改变的数据,所以你无法撤消它。

为什么不保留所有节点,除非用户显式尝试删除它们?最终用户总是可以选择在他的最终结果中被剔除的东西。

您也可以尝试使用树状结构。

答案 1 :(得分:0)

如果您只关心与某个键相关的最顶层节点,并且有时需要迭代所有节点,您可以从节点构建链接列表。这允许您迭代节点并按键检索相关节点。但是,它会增加节点的内存消耗。您可以通过创建Node的子类来最小化这一点,该子类保留Next属性,同时保留正常节点而不存在底层节点。这可能会减慢迭代速度。

public Node Next { get; set; }

public Node()
{
    Node next;
    if (dic.TryGetValue(key, out next))
        this.Next = next;
    dic[key] = this;
}