双向映射的数据结构

Mat*_*ero 2 c# mapping types data-structures

现在,在你责骂我之前,我知道有一个非常相似的问题:

双向映射的最佳数据结构?

事实上,我正在寻找一种能够完成同样事情的数据结构。具体来说,我有一个字符串应该映射到另一个字符串,并且其他字符串也应该映射到原始字符串。

例如:

".jpg" -> "image/jpeg"
"image/jpeg" -> ".jpg"
Run Code Online (Sandbox Code Playgroud)

链接的问题建议使用某种哈希图或Dictionary<string,string>来完成此任务。

人们将拥有一种自定义数据类型,该类型将保存两个字典,每个字典都是一种映射方式。这将提供 O(1),但我发现它根本不可扩展

考虑到我有一个字典,其中包含从 200 个 MIME 类型到关联文件扩展名的所有映射,我需要创建一个类似的字典,内容相同但相反。这很容易出现拼写错误或丢失键,并且有很多重复的代码。

虽然链接的问题旨在Java中的解决方案,但我正在寻找C#中的解决方案。

是否有.NET 数据结构支持对象之间的这种双向映射?

如果没有,我如何在不复制代码的情况下完成此任务(如两个字典解决方案中所示)?

Dav*_*ych 5

为什么带有两个字典的自定义类型不起作用?尽管它会使用双倍的内存,但它允许 O(1) 查找并且应该按照您的需要工作。

然而,当涉及到通用参数时,它可能会变得有点棘手。如果您指定相同的类型,这不是问题,但是如果您指定不同的类型,索引器就会中断,因为您只能以一种方式获取值。如果索引器超载并且有两个,即:

public K this[T value]
public T this[K value]
Run Code Online (Sandbox Code Playgroud)

如果您有相同的参数,它就会崩溃,因为它无法解决。在这种情况下,我建议有两个不同的课程:

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));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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));
        }
    }
}    
Run Code Online (Sandbox Code Playgroud)

这将允许您像评论中提到的那样使用它:

var dict = new TwoWayDictionary<string>();
dict.Add(".jpg", "image/jpg");
var mime = dict[".jpg"];
var ext = dict["image/jpg"];
Run Code Online (Sandbox Code Playgroud)

如果需要,请指定 2 种不同的类型:

var dict = new TwoWayDictionary<string, int>();
dict.Add(".jpg", 100);
var number = dict[".jpg"];
var ext = dict[100];
Run Code Online (Sandbox Code Playgroud)