键值依赖于值的键值对集合
collection of key-value pairs where key depends on value
我有一个classMyClass
class MyClass
{
public string Name { get; set; } // is unique among all instances
public SomeClass Data { get; set; }
...
}
其中我想将几个实例存储在一个集合中。我经常需要检查具有特定名称的实例是否存在,如果存在,则检索该实例。由于遍历整个集合不是一个选项(性能!),我想到了使用键值对的集合,例如一个 IDictionary<string, MyClass>
.
我的程序也将允许重命名 MyClass
的实例(如果违反名称唯一性则不允许重命名)。但是如果我重命名 MyClass
,我还需要从字典中删除旧条目并添加新条目(即使用新名称)以保持数据一致。
问题是我到处都有几个这样的词典(其中包含所有 MyClass
实例的子集),并且很难跟踪它们并在每次更新后持续更新所有词典重命名。
有没有办法让键值对自动保持一致?我想我听说过一种允许这样做的数据结构,它至少存在于 C++ 中(不幸的是,我不知道它是如何被调用的)。基本上,它应该是一个集合,其中的键不仅仅是一个普通字符串,更像是对字符串的引用(在本例中是对名称 属性 的引用),但其行为就好像它是一个字符串一样。 C#中有这样的东西吗?您对如何保持集合的一致性有其他想法吗?
我唯一的想法是在我的程序的最高级别收集所有词典,并使重命名方法在实际重命名过程后更新所有这些词典。但一定有更好的方法!
为什么这个问题不是 Best way to change dictionary key 的重复问题:
我已经知道字典不允许更改键值。相反,我要求另一种数据结构以某种方式与关键更改兼容(不会完全失去性能优势),并且我也要求其他方法。所以我的问题对任何方向的输入都更加开放,只要它有助于解决保持数据一致的问题。
我认为没有本地集合可以做到这一点。但是,您只需在您的基础中添加某种通知即可轻松创建自己的 class.
public class ChangingNameObject
{
public delegate void ObjectNameChange(string oldName, string newName);
public event ObjectNameChange ObjectNameChanged;
private string name;
public string Name
{
get => name;
set
{
ObjectNameChanged?.Invoke(name, value);
name = value;
}
}
}
public class WatchingDictionary
{
private Dictionary<string, ChangingNameObject> content = new Dictionary<string, ChangingNameObject>();
public void Add(ChangingNameObject item)
{
item.ObjectNameChanged += UpdatePosition;
content[item.Name] = item;
}
public void Remove(ChangingNameObject item)
{
item.ObjectNameChanged -= UpdatePosition;
content.Remove(item.Name);
}
private void UpdatePosition(string oldname, string newname)
{
var o = content[oldname];
content.Remove(oldname);
content.Add(newname, o);
}
}
我只写了最基本的东西,你错过了所有的访问器和枚举器,只需添加你需要的。
枚举时要非常小心,因为在枚举期间更改集合会导致失败(并且由于集合是隐藏的,您可能在不知情的情况下这样做)
据我了解,你的问题是这样的:
- 你有多个词典,每个词典都有你的一部分数据
- 您的所有实例在所有字典中都应具有唯一的名称
- 更改名称时:
- 首先,检查这个名字是否仍然是唯一的
- 在它所在的任何字典中更新它
我想我会以不同的方式解决这个问题。
首先,将 ID 字段添加到 class 中,这将是一个 Guid / 运行 数字,该字段从创建实例的那一刻起就永远不会改变。
接下来,添加另一个字典,它只包含 个实例的名称和 ID,它应该看起来像这样:
[{"FirstName": "Guid1"},
{"SecondName": "Guid2"},
{"ThirdName": "Guid3"}]
您的其他词典将把 ID 作为键,而不是名字:
[{"Guid1": {instance1}},
{"Guid2": {instance2}}]
现在,当您更改实例的名称时,所有名称都存在于一个字典中,该字典会告诉您它是否已经存在。而且你只需要在一个地方改变它,因为其余的字典依赖于一个永远不会改变的常量值。
所以假设你想更改 "FirstName"
的名称,名称字典将如下所示:
[{"OtherName": "Guid1"},
{"SecondName": "Guid2"},
{"ThirdName": "Guid3"}]
其余数据无需更改。
我有一个classMyClass
class MyClass
{
public string Name { get; set; } // is unique among all instances
public SomeClass Data { get; set; }
...
}
其中我想将几个实例存储在一个集合中。我经常需要检查具有特定名称的实例是否存在,如果存在,则检索该实例。由于遍历整个集合不是一个选项(性能!),我想到了使用键值对的集合,例如一个 IDictionary<string, MyClass>
.
我的程序也将允许重命名 MyClass
的实例(如果违反名称唯一性则不允许重命名)。但是如果我重命名 MyClass
,我还需要从字典中删除旧条目并添加新条目(即使用新名称)以保持数据一致。
问题是我到处都有几个这样的词典(其中包含所有 MyClass
实例的子集),并且很难跟踪它们并在每次更新后持续更新所有词典重命名。
有没有办法让键值对自动保持一致?我想我听说过一种允许这样做的数据结构,它至少存在于 C++ 中(不幸的是,我不知道它是如何被调用的)。基本上,它应该是一个集合,其中的键不仅仅是一个普通字符串,更像是对字符串的引用(在本例中是对名称 属性 的引用),但其行为就好像它是一个字符串一样。 C#中有这样的东西吗?您对如何保持集合的一致性有其他想法吗?
我唯一的想法是在我的程序的最高级别收集所有词典,并使重命名方法在实际重命名过程后更新所有这些词典。但一定有更好的方法!
为什么这个问题不是 Best way to change dictionary key 的重复问题:
我已经知道字典不允许更改键值。相反,我要求另一种数据结构以某种方式与关键更改兼容(不会完全失去性能优势),并且我也要求其他方法。所以我的问题对任何方向的输入都更加开放,只要它有助于解决保持数据一致的问题。
我认为没有本地集合可以做到这一点。但是,您只需在您的基础中添加某种通知即可轻松创建自己的 class.
public class ChangingNameObject
{
public delegate void ObjectNameChange(string oldName, string newName);
public event ObjectNameChange ObjectNameChanged;
private string name;
public string Name
{
get => name;
set
{
ObjectNameChanged?.Invoke(name, value);
name = value;
}
}
}
public class WatchingDictionary
{
private Dictionary<string, ChangingNameObject> content = new Dictionary<string, ChangingNameObject>();
public void Add(ChangingNameObject item)
{
item.ObjectNameChanged += UpdatePosition;
content[item.Name] = item;
}
public void Remove(ChangingNameObject item)
{
item.ObjectNameChanged -= UpdatePosition;
content.Remove(item.Name);
}
private void UpdatePosition(string oldname, string newname)
{
var o = content[oldname];
content.Remove(oldname);
content.Add(newname, o);
}
}
我只写了最基本的东西,你错过了所有的访问器和枚举器,只需添加你需要的。
枚举时要非常小心,因为在枚举期间更改集合会导致失败(并且由于集合是隐藏的,您可能在不知情的情况下这样做)
据我了解,你的问题是这样的:
- 你有多个词典,每个词典都有你的一部分数据
- 您的所有实例在所有字典中都应具有唯一的名称
- 更改名称时:
- 首先,检查这个名字是否仍然是唯一的
- 在它所在的任何字典中更新它
我想我会以不同的方式解决这个问题。
首先,将 ID 字段添加到 class 中,这将是一个 Guid / 运行 数字,该字段从创建实例的那一刻起就永远不会改变。
接下来,添加另一个字典,它只包含 个实例的名称和 ID,它应该看起来像这样:
[{"FirstName": "Guid1"},
{"SecondName": "Guid2"},
{"ThirdName": "Guid3"}]
您的其他词典将把 ID 作为键,而不是名字:
[{"Guid1": {instance1}},
{"Guid2": {instance2}}]
现在,当您更改实例的名称时,所有名称都存在于一个字典中,该字典会告诉您它是否已经存在。而且你只需要在一个地方改变它,因为其余的字典依赖于一个永远不会改变的常量值。
所以假设你想更改 "FirstName"
的名称,名称字典将如下所示:
[{"OtherName": "Guid1"},
{"SecondName": "Guid2"},
{"ThirdName": "Guid3"}]
其余数据无需更改。