首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >字典与KeyValuePair

字典与KeyValuePair
EN

Stack Overflow用户
提问于 2011-09-01 14:38:29
回答 3查看 2.8K关注 0票数 1

我对字典有意见,希望你能帮我。

我有以下声明:

代码语言:javascript
复制
class MainCollection<TKey1, TKey2, TValue> : Dictionary<KeyValuePair<TKey1, TKey2>, TValue>

问题是,我无法从本词典中获得一个由TKey1 TKey2提供的元素。是否只有TKey1或TKey2才能获得元素,而不是TKey1和TKey2?

我编写了以下代码:

代码语言:javascript
复制
 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 ==键=>操作符==不能应用于int和TKey1
  2. 类型,看起来很难看。即使编译成功,我也不确定这是否是获取此类项目的最快方法。我想字典应该做得更好。--

我怎样才能解决这些错误?我在这里没有发现任何相关的问题。提前感谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-01 14:42:36

好的,所以您希望能够通过TKey1TKey2进行查找。然后你想要的是三本字典,每个键一本,然后一本钥匙对。

代码语言:javascript
复制
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返回集合。

剩下的细节交给你。

关键是,如果您希望快速查找任何一个键,您需要两个字典(一个为每个坐标的密钥对)。使用一个键可以通过查询键集来工作,但这很慢(搜索键是线性的)。

票数 5
EN

Stack Overflow用户

发布于 2011-09-01 14:42:07

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

代码语言:javascript
复制
 public TValue GetItemByKey1(TKey1 key)
 {         
     var value = from s in this.Keys where s.Key.Key == key select this[s];
     return value.SingleOrDefault();
 }

对于TKey2,您可以有类似的方法。

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

票数 1
EN

Stack Overflow用户

发布于 2011-09-01 15:16:22

我建议不要使用KeyValuePair<TKey, TValue>,因为KVP是一个结构,并且作为字典中的一个键表示对象将存在一段时间。我会推荐一个Tuple<T1, T2>代替。它的好处是元组是一种参考类型,您可以自由地传递而不复制。而且,Tuple是一个只读对象,就像KVPair一样。以下是我写它的方式:

代码语言:javascript
复制
    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; } }
    }
}

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

更新

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

代码语言:javascript
复制
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]];
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7271927

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档