字典和键值对

发布于 2024-12-02 15:10:59 字数 739 浏览 0 评论 0原文

我在使用字典时遇到问题,希望你能帮助我。

我有以下声明:

class MainCollection<TKey1, TKey2, TValue> : Dictionary<KeyValuePair<TKey1, TKey2>, TValue>

问题是我无法通过 TKey1 OR TKey2 从该字典中获取元素。 有没有办法仅通过 TKey1 OR TKey2 而不是 TKey1 AND TKey2 来获取元素?

我写了下面的代码:

 public TValue GetItemByKey1(TKey1 key)
 {
     MainCollection<int, int, string> Coll = new MainCollection<int, int, string>();
     var value = from s in Coll where s.Key.Key == key select s.Value;
 }

但它已经有两个问题:

  1. 编译错误: s.Key.Key == key =>运算符 == 不能应用于 int 和 TKey1 类型
  2. 它看起来很难看。即使编译成功,我也不确定这是获取此类项目的最快方法。我想字典应该更好。

我该如何解决此类错误?我在这里没有找到任何相关问题。 提前致谢!

i have a problem with Dictionary, hope you'll help me.

I have the following declaration:

class MainCollection<TKey1, TKey2, TValue> : Dictionary<KeyValuePair<TKey1, TKey2>, TValue>

The problem is that i cant get an element from this dictionary by TKey1 OR TKey2.
Is there a way to get an element only by TKey1 OR TKey2, not TKey1 AND TKey2?

I wrote the following code:

 public TValue GetItemByKey1(TKey1 key)
 {
     MainCollection<int, int, string> Coll = new MainCollection<int, int, string>();
     var value = from s in Coll where s.Key.Key == key select s.Value;
 }

But it already has two issues:

  1. Compilation error: s.Key.Key == key => operator == can not be applied to types int and TKey1
  2. It looks ugly. Even if compilation would be successful I'm not sure that this is the fastest way to get such items. I guess that Dictionary should something better.

How can i solve such errors? I didnt find any related questions here.
Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

情未る 2024-12-09 15:10:59

好的,您希望能够通过 TKey1TKey2 进行查找。那么您需要的是三个字典,一个用于每个密钥,然后一个用于密钥对。

class Foo<TFirstKey, TSecondKey, TValue> {
    private readonly Dictionary<TFirstKey, List<TValue>> firstDictionary
        = new Dictionary<TFirstKey, List<TValue>>();
    private readonly Dictionary<TSecondKey, List<TValue>> secondDictionary
        = new Dictionary<TSecondKey, List<TValue>>();
    private Dictionary<Tuple<TFirstKey, TSecondKey>, TValue> dictionary
        = new Dictionary<Tuple<TFirstKey, TSecondKey>, TValue>();

    public IEnumerable<TValue> GetByFirstKey(TFirstKey firstKey) {
        return this.firstDictionary[firstKey];
    }

    public IEnumerable<TValue> GetBySecondKey(TSecondKey secondKey) {
        return this.secondDictionary[secondKey];
    }

    public TValue GetByKey(TFirstKey firstKey, TSecondKey secondKey) {
        return this.dictionary[Tuple.Create(firstKey, secondKey)];
    }

    public void Add(TFirstKey firstKey, TSecondKey secondKey, TValue value) {
        this.dictionary.Add(Tuple.Create(firstKey, secondKey), value);
        if(this.firstDictionary.Keys.Contains(firstKey)) {
            this.firstDictionary[firstKey].Add(value);
        }
        else {
            this.firstDictionary.Add(firstKey, new List<TValue> { value });
        }
         if(this.secondDictionary.Keys.Contains(secondKey)) {
            this.secondDictionary[secondKey].Add(value);
        }
        else {
            this.secondDictionary.Add(secondKey, new List<TValue> { value });
        }
    }
}

请注意,只有 (TFirstKey, TSecondKey) 的查找是唯一的,因此您需要 GetByFirstKeyGetBySecondKey 来返回集合。

我会将其余的细节留给您。

要点是,如果您想快速查找任一键,则需要两个字典(一个对应键对的每个坐标)。可以通过查询键集来使用它,但这很慢(搜索键是线性的)。

Okay, so you want to be able to lookup by TKey1 or TKey2. Then what you want is three dictionaries, one for each of the keys, and then one for the key-pairs.

class Foo<TFirstKey, TSecondKey, TValue> {
    private readonly Dictionary<TFirstKey, List<TValue>> firstDictionary
        = new Dictionary<TFirstKey, List<TValue>>();
    private readonly Dictionary<TSecondKey, List<TValue>> secondDictionary
        = new Dictionary<TSecondKey, List<TValue>>();
    private Dictionary<Tuple<TFirstKey, TSecondKey>, TValue> dictionary
        = new Dictionary<Tuple<TFirstKey, TSecondKey>, TValue>();

    public IEnumerable<TValue> GetByFirstKey(TFirstKey firstKey) {
        return this.firstDictionary[firstKey];
    }

    public IEnumerable<TValue> GetBySecondKey(TSecondKey secondKey) {
        return this.secondDictionary[secondKey];
    }

    public TValue GetByKey(TFirstKey firstKey, TSecondKey secondKey) {
        return this.dictionary[Tuple.Create(firstKey, secondKey)];
    }

    public void Add(TFirstKey firstKey, TSecondKey secondKey, TValue value) {
        this.dictionary.Add(Tuple.Create(firstKey, secondKey), value);
        if(this.firstDictionary.Keys.Contains(firstKey)) {
            this.firstDictionary[firstKey].Add(value);
        }
        else {
            this.firstDictionary.Add(firstKey, new List<TValue> { value });
        }
         if(this.secondDictionary.Keys.Contains(secondKey)) {
            this.secondDictionary[secondKey].Add(value);
        }
        else {
            this.secondDictionary.Add(secondKey, new List<TValue> { value });
        }
    }
}

Note that only lookup by (TFirstKey, TSecondKey) is unique, so you need GetByFirstKey and GetBySecondKey to return collections.

I'll leave the rest of the details to you.

The point is that if you want fast lookups on either key, you need two dictionaries (one for each coordinate of the key-pair). Using one can be made to work by querying the key set, but that's slow (it's linear to search the keys).

鸠书 2024-12-09 15:10:59

只需向集合本身添加一个方法:

 public TValue GetItemByKey1(TKey1 key)
 {         
     var value = from s in this.Keys where s.Key.Key == key select this[s];
     return value.SingleOrDefault();
 }

您可以为 TKey2 使用类似的方法。

请注意,这些查找将比标准字典键查找慢得多,因为您正在迭代键集合,而不是利用字典本来使用的哈希表。

Just add a method to the collection itself:

 public TValue GetItemByKey1(TKey1 key)
 {         
     var value = from s in this.Keys where s.Key.Key == key select this[s];
     return value.SingleOrDefault();
 }

You can have a similar method for TKey2.

Note that these lookups will be much slower than a standard dictionary key lookup, since you're iterating the key collection, rather than taking advantage of the hashtable a dictionary would otherwise use.

沉睡月亮 2024-12-09 15:10:59

我建议不要使用 KeyValuePair 因为 KVP 是一个结构体,并且作为字典中的键表明该对象将存在一段时间。我会推荐使用 Tuple 。好处是Tuple是引用类型,可以自由传递,无需复制。此外,Tuple 是一个只读对象,就像 KVPair 一样。这是我的编写方式:

    class Program
    {
        static void Main(string[] args)
        {
            MainCollection<int, string, DateTime> collection = new MainCollection<int, string, DateTime>();

            collection.Add(Tuple<int, string>.Create(1, "Bob"), new DateTime(1992, 12, 1));
            collection.Add(Tuple<int, string>.Create(2, "James"), new DateTime(1945, 9, 1));
            collection.Add(Tuple<int, string>.Create(3, "Julie"), new DateTime(1976, 7, 15));

            DateTime date;

            date = collection.GetValue(1);
            Console.WriteLine("Bob birthdate: {0}", date);

            date = collection.GetValue("Julie");
            Console.WriteLine("#3 birthdate: {0}", date);

            Console.ReadLine();
        }
    }

    public class MainCollection<TKey1, TKey2, TValue>
    {
        Tuple<TKey1, TKey2> key;
        Dictionary<Tuple<TKey1, TKey2>, TValue> mainCollection = new Dictionary<Tuple<TKey1, TKey2>, TValue>();

        public void Add(Tuple<TKey1, TKey2> Key, TValue Value)
        {
            mainCollection.Add(Key, Value);
        }

        public TValue GetValue(TKey1 Key)
        {
            return mainCollection.Where(k => k.Key.Item1.Equals(Key))
                                 .Select(v => v.Value)
                                 .FirstOrDefault();
        }

        public TValue GetValue(TKey2 Key)
        {
            return mainCollection.Where(k => k.Key.Item2.Equals(Key))
                                 .Select(v => v.Value)
                                 .FirstOrDefault();
        }

    }

    public class Tuple<T1, T2>
    {
        readonly T1 item1;
        readonly T2 item2;

        Tuple(T1 item1, T2 item2)
        {
            this.item1 = item1;
            this.item2 = item2;
        }

        public static Tuple<T1, T2> Create(T1 Item1, T2 Item2)
        {
            return new Tuple<T1, T2>(Item1, Item2);
        }

        public T1 Item1
        { get { return item1; } }

        public T2 Item2
        { get { return item2; } }
    }
}

注意:我包含了一个 Tuple 实现,以防您不使用 .Net 4.0

更新
MainCollection 对象转换为使用多个字典将如下所示:

public class MainCollection<TKey1, TKey2, TValue>
{
    Tuple<TKey1, TKey2> key;
    Dictionary<TKey1, Tuple<TKey1, TKey2>> k1Dictionary = new Dictionary<TKey1, Tuple<TKey1, TKey2>>();
    Dictionary<TKey2, Tuple<TKey1, TKey2>> k2Dictionary = new Dictionary<TKey2, Tuple<TKey1, TKey2>>();
    Dictionary<Tuple<TKey1, TKey2>, TValue> mainCollection = new Dictionary<Tuple<TKey1, TKey2>, TValue>();

    public void Add(Tuple<TKey1, TKey2> Key, TValue Value)
    {
        mainCollection.Add(Key, Value);

        k1Dictionary.Add(Key.Item1, Key);
        k2Dictionary.Add(Key.Item2, Key);
    }

    public TValue GetValue(TKey1 Key)
    {
        return mainCollection[k1Dictionary[Key]];
    }

    public TValue GetValue(TKey2 Key)
    {
        return mainCollection[k2Dictionary[Key]];
    }
}

I recommend against using KeyValuePair<TKey, TValue> because KVP is a struct and being a key in the dictionary indicates that the object will be around for a while. I would recommend a Tuple<T1, T2> instead. The benefit is that Tuple is a reference type and you can freely pass around without making copies. Also, Tuple is a readonly object just like the KVPair. Here's the way I would write it:

    class Program
    {
        static void Main(string[] args)
        {
            MainCollection<int, string, DateTime> collection = new MainCollection<int, string, DateTime>();

            collection.Add(Tuple<int, string>.Create(1, "Bob"), new DateTime(1992, 12, 1));
            collection.Add(Tuple<int, string>.Create(2, "James"), new DateTime(1945, 9, 1));
            collection.Add(Tuple<int, string>.Create(3, "Julie"), new DateTime(1976, 7, 15));

            DateTime date;

            date = collection.GetValue(1);
            Console.WriteLine("Bob birthdate: {0}", date);

            date = collection.GetValue("Julie");
            Console.WriteLine("#3 birthdate: {0}", date);

            Console.ReadLine();
        }
    }

    public class MainCollection<TKey1, TKey2, TValue>
    {
        Tuple<TKey1, TKey2> key;
        Dictionary<Tuple<TKey1, TKey2>, TValue> mainCollection = new Dictionary<Tuple<TKey1, TKey2>, TValue>();

        public void Add(Tuple<TKey1, TKey2> Key, TValue Value)
        {
            mainCollection.Add(Key, Value);
        }

        public TValue GetValue(TKey1 Key)
        {
            return mainCollection.Where(k => k.Key.Item1.Equals(Key))
                                 .Select(v => v.Value)
                                 .FirstOrDefault();
        }

        public TValue GetValue(TKey2 Key)
        {
            return mainCollection.Where(k => k.Key.Item2.Equals(Key))
                                 .Select(v => v.Value)
                                 .FirstOrDefault();
        }

    }

    public class Tuple<T1, T2>
    {
        readonly T1 item1;
        readonly T2 item2;

        Tuple(T1 item1, T2 item2)
        {
            this.item1 = item1;
            this.item2 = item2;
        }

        public static Tuple<T1, T2> Create(T1 Item1, T2 Item2)
        {
            return new Tuple<T1, T2>(Item1, Item2);
        }

        public T1 Item1
        { get { return item1; } }

        public T2 Item2
        { get { return item2; } }
    }
}

NOTE: I included a Tuple implementation in case you are not using .Net 4.0

Update:
Converting the MainCollection object to use multiple dictionaries would look like this:

public class MainCollection<TKey1, TKey2, TValue>
{
    Tuple<TKey1, TKey2> key;
    Dictionary<TKey1, Tuple<TKey1, TKey2>> k1Dictionary = new Dictionary<TKey1, Tuple<TKey1, TKey2>>();
    Dictionary<TKey2, Tuple<TKey1, TKey2>> k2Dictionary = new Dictionary<TKey2, Tuple<TKey1, TKey2>>();
    Dictionary<Tuple<TKey1, TKey2>, TValue> mainCollection = new Dictionary<Tuple<TKey1, TKey2>, TValue>();

    public void Add(Tuple<TKey1, TKey2> Key, TValue Value)
    {
        mainCollection.Add(Key, Value);

        k1Dictionary.Add(Key.Item1, Key);
        k2Dictionary.Add(Key.Item2, Key);
    }

    public TValue GetValue(TKey1 Key)
    {
        return mainCollection[k1Dictionary[Key]];
    }

    public TValue GetValue(TKey2 Key)
    {
        return mainCollection[k2Dictionary[Key]];
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文