双向映射的数据结构
Data structure for two way mapping
现在,在你骂我之前,我知道有一个非常类似的问题:
Best data structure for two way mapping?
事实上,我正在寻找一种可以完成同样事情的数据结构。具体来说,我有一个字符串应该映射到另一个字符串,而另一个字符串也应该映射到原始字符串。
例如:
".jpg" -> "image/jpeg"
"image/jpeg" -> ".jpg"
链接的问题建议使用某种哈希图或 Dictionary<string,string>
来完成此操作。
一个自定义数据类型将包含两个字典,每个字典是一种映射方式。这将提供 O(1),但我发现它 根本不可扩展 。
考虑到我有一个字典,其中包含从 200 种 MIME 类型到相关文件扩展名的所有映射,我需要创建一个类似的字典,内容相同但相反。这很容易出现拼写错误或遗漏键,并且有很多重复代码。
尽管链接的问题旨在 Java 中寻找解决方案,但我正在寻找 C# 中的解决方案。
是否有支持对象之间这种双向映射的 .NET 数据结构?
如果没有,我如何在不复制代码的情况下完成此操作(如在两个词典解决方案中那样)?
为什么带有两个字典的自定义类型不起作用?虽然它会使用双倍的内存,但它允许 O(1) 查找并且应该可以按您的需要工作。
但是,当涉及到泛型参数时,它可能会变得有点毛茸茸。如果您指定相同的类型,这不是问题,但是如果您指定不同的类型,索引器就会中断,因为您只能通过一种方式获取值。如果您重载索引器并有两个,即:
public K this[T value]
public T this[K value]
如果你有相同的参数,它会崩溃,因为它无法解析。在那种情况下,我建议有两个不同的 类:
public class TwoWayDictionary<T>
{
private Dictionary<T, T> _first;
private Dictionary<T, T> _second;
public TwoWayDictionary()
{
_first = new Dictionary<T, T>();
_second = new Dictionary<T, T>();
}
public void Add(T first, T second)
{
_first.Add(first, second);
_second.Add(second, first);
}
public T this[T value]
{
get
{
if(_first.ContainsKey(value))
{
return _first[value];
}
if(_second.ContainsKey(value))
{
return _second[value];
}
throw new ArgumentException(nameof(value));
}
}
}
和
public class TwoWayDictionary<T, K>
{
private readonly Dictionary<T, K> _first;
private readonly Dictionary<K, T> _second;
public TwoWayDictionary()
{
_first = new Dictionary<T, K>();
_second = new Dictionary<K, T>();
}
public void Add(T first, K second)
{
_first.Add(first, second);
_second.Add(second, first);
}
public K this[T value]
{
get
{
if (_first.ContainsKey(value))
{
return _first[value];
}
throw new ArgumentException(nameof(value));
}
}
public T this[K value]
{
get
{
if (_second.ContainsKey(value))
{
return _second[value];
}
throw new ArgumentException(nameof(value));
}
}
}
这将允许您像评论中提到的那样使用它:
var dict = new TwoWayDictionary<string>();
dict.Add(".jpg", "image/jpg");
var mime = dict[".jpg"];
var ext = dict["image/jpg"];
并根据需要指定 2 种不同的类型:
var dict = new TwoWayDictionary<string, int>();
dict.Add(".jpg", 100);
var number = dict[".jpg"];
var ext = dict[100];
现在,在你骂我之前,我知道有一个非常类似的问题:
Best data structure for two way mapping?
事实上,我正在寻找一种可以完成同样事情的数据结构。具体来说,我有一个字符串应该映射到另一个字符串,而另一个字符串也应该映射到原始字符串。
例如:
".jpg" -> "image/jpeg"
"image/jpeg" -> ".jpg"
链接的问题建议使用某种哈希图或 Dictionary<string,string>
来完成此操作。
一个自定义数据类型将包含两个字典,每个字典是一种映射方式。这将提供 O(1),但我发现它 根本不可扩展 。
考虑到我有一个字典,其中包含从 200 种 MIME 类型到相关文件扩展名的所有映射,我需要创建一个类似的字典,内容相同但相反。这很容易出现拼写错误或遗漏键,并且有很多重复代码。
尽管链接的问题旨在 Java 中寻找解决方案,但我正在寻找 C# 中的解决方案。
是否有支持对象之间这种双向映射的 .NET 数据结构?
如果没有,我如何在不复制代码的情况下完成此操作(如在两个词典解决方案中那样)?
为什么带有两个字典的自定义类型不起作用?虽然它会使用双倍的内存,但它允许 O(1) 查找并且应该可以按您的需要工作。
但是,当涉及到泛型参数时,它可能会变得有点毛茸茸。如果您指定相同的类型,这不是问题,但是如果您指定不同的类型,索引器就会中断,因为您只能通过一种方式获取值。如果您重载索引器并有两个,即:
public K this[T value]
public T this[K value]
如果你有相同的参数,它会崩溃,因为它无法解析。在那种情况下,我建议有两个不同的 类:
public class TwoWayDictionary<T>
{
private Dictionary<T, T> _first;
private Dictionary<T, T> _second;
public TwoWayDictionary()
{
_first = new Dictionary<T, T>();
_second = new Dictionary<T, T>();
}
public void Add(T first, T second)
{
_first.Add(first, second);
_second.Add(second, first);
}
public T this[T value]
{
get
{
if(_first.ContainsKey(value))
{
return _first[value];
}
if(_second.ContainsKey(value))
{
return _second[value];
}
throw new ArgumentException(nameof(value));
}
}
}
和
public class TwoWayDictionary<T, K>
{
private readonly Dictionary<T, K> _first;
private readonly Dictionary<K, T> _second;
public TwoWayDictionary()
{
_first = new Dictionary<T, K>();
_second = new Dictionary<K, T>();
}
public void Add(T first, K second)
{
_first.Add(first, second);
_second.Add(second, first);
}
public K this[T value]
{
get
{
if (_first.ContainsKey(value))
{
return _first[value];
}
throw new ArgumentException(nameof(value));
}
}
public T this[K value]
{
get
{
if (_second.ContainsKey(value))
{
return _second[value];
}
throw new ArgumentException(nameof(value));
}
}
}
这将允许您像评论中提到的那样使用它:
var dict = new TwoWayDictionary<string>();
dict.Add(".jpg", "image/jpg");
var mime = dict[".jpg"];
var ext = dict["image/jpg"];
并根据需要指定 2 种不同的类型:
var dict = new TwoWayDictionary<string, int>();
dict.Add(".jpg", 100);
var number = dict[".jpg"];
var ext = dict[100];