在C#中有双向字典/双向字典吗?

33 浏览
0 Comments

在C#中有双向字典/双向字典吗?

我想以以下方式存储字典中的单词:

通过单词获取单词代码:dict["SomeWord"] -> 123,通过单词代码获取单词:dict[123] -> "SomeWord"

这可行吗?当然,一种方法是使用两个字典:DictionaryDictionary,但是否还有其他方法?

0
0 Comments

在C#中,如果我们需要一个双向字典(Two-way / bidirectional Dictionary),即可以根据键找到值,也可以根据值找到键,那么遗憾的是我们需要使用两个字典,一个用于正向查找,另一个用于反向查找。然而,我们可以使用LINQ轻松地获取反向字典:

Dictionary<T1, T2> dict = new Dictionary<T1, T2>();
Dictionary<T2, T1> dictInverse = dict.ToDictionary((i) => i.Value, (i) => i.Key);

虽然这种方法很方便,但如果我们经常访问反向字典,性能就不会很好。每次需要反向字典时,动态创建一个新的字典是很昂贵的。

只是一个小细节:如果字典不会改变,那么访问反向字典实际上不会更加昂贵。我们需要在修改字典时更新/重新生成反向字典,这是一个昂贵的操作。

因此,为了解决这个问题,我们需要找到一种更高效的方法来创建和更新双向字典。

0
0 Comments

在上述代码中,我们看到了一个C#中的双向字典(Two-way / bidirectional Dictionary)的实现。双向字典是一种可以通过键或值来访问数据的数据结构。该代码通过添加初始化和Contains方法来扩展了Enigmativity代码。

首先,我们定义了一个名为Map的泛型类,它包含了两个私有的Dictionary成员变量_forward和_reverse,分别用于存储正向和反向的键值对。我们通过Indexer类将其封装成可读写的属性Forward和Reverse。

在Map类中,我们实现了Add和Remove方法用于向字典中添加和删除键值对。在Remove方法中,我们通过正向和反向的键值对来删除对应的项。

为了实现迭代功能,我们实现了IEnumerable接口,并通过GetEnumerator方法返回_forward字典的迭代器。

接下来,我们看到了一个使用双向字典的示例用法,用于检查括号的有效性。我们定义了一个名为ValidParenthesisExt的静态类,其中包含了一个名为IsValidParenthesis的扩展方法。这个方法接受一个字符串作为输入,并使用双向字典_parenthesis来检查括号的有效性。

在IsValidParenthesis方法中,我们创建了一个栈来存储遇到的左括号。然后,我们遍历输入字符串中的每个字符。如果字符是左括号,则将其压入栈中。如果字符是右括号,则从栈中弹出一个左括号,并通过双向字典_parenthesis的Reverse属性来获取对应的左括号。如果这两个括号不匹配,则返回false。最后,如果栈为空,则表示所有的括号都匹配,返回true。

在最后的注释中,提到了一个可能出现问题的地方。由于双向字典的特性,我们可以通过正向和反向的键值对来访问值。这可能导致字典中的值被指向了另一对的值,从而破坏了字典的一致性。为了避免这种情况,我们需要谨慎使用双向字典,并确保在修改字典中的值时保持一致性。

通过以上代码,我们了解了在C#中实现双向字典的方法,并看到了一个使用双向字典的示例。双向字典在某些场景下非常有用,可以方便地通过键或值进行查询和操作。但是需要注意的是,在使用双向字典时要注意保持字典的一致性,避免出现意外的结果。

0
0 Comments

在这段对话中,问题的出现是因为作者想要实现一个C#中的双向字典(Two-way / bidirectional Dictionary),即可以根据键找到值,也可以根据值找到键。为了解决这个问题,作者提供了一个Map类的实现,并使用了两个Dictionary来实现双向字典的功能。下面是这个Map类的定义:

public class Map
{
    private Dictionary _forward = new Dictionary();
    private Dictionary _reverse = new Dictionary();
    public Map()
    {
        this.Forward = new Indexer(_forward);
        this.Reverse = new Indexer(_reverse);
    }
    public class Indexer
    {
        private Dictionary _dictionary;
        public Indexer(Dictionary dictionary)
        {
            _dictionary = dictionary;
        }
        public T4 this[T3 index]
        {
            get { return _dictionary[index]; }
            set { _dictionary[index] = value; }
        }
    }
    public void Add(T1 t1, T2 t2)
    {
        _forward.Add(t1, t2);
        _reverse.Add(t2, t1);
    }
    public Indexer Forward { get; private set; }
    public Indexer Reverse { get; private set; }
}

这个Map类有两个私有的Dictionary字段,分别用于正向和反向查找。同时,还有一个Indexer类用于实现索引器语法。在Add方法中,同时向两个Dictionary中添加键值对。

然而,这段代码存在一些问题。在异常处理方面,可能会出现只有_forward成功添加了键值对,而_reverse添加失败的情况,导致字典处于部分添加的状态。另外,Indexer类中的setter方法会破坏正向和反向查找的一致性。

对于异常处理问题,可以在Add方法中使用try...catch语句来捕获异常,保证两个Dictionary的一致性。对于setter方法的问题,可以通过传递两个Dictionary给Indexer类,并在setter方法中同时更新两个Dictionary来解决。

最后,还提到了有一个名为"nuget.org/packages/BidirectionalMap"的nuget包,提供了一个扩展版的双向字典实现。

这段对话讨论了如何在C#中实现双向字典,并解决了其中的一些问题。通过使用两个Dictionary和Indexer类,可以实现根据键找到值,也可以根据值找到键的功能。

0