4

I have list declared as

 List<KeyValuePair<string, Int64>> KPList = new List<KeyValuePair<string, long>>(); 

I need to check if a combination of key and value already exists. I can't use dictionary since I need to have unique combination of key and value where in case a key will have multiple values but as a single pair

if(!KPList.Any(p=> p.Key ==keyp && p.Value == valuep))

What is wrong in this?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Jameer Basha
  • 61
  • 1
  • 9
  • 2
    What makes you think something's wrong? You could use `Tuple` instead of `KeyValuePair` if you're on at least .Net 3.5 (iirc), but otherwise, seems fine - assuming you're OK with O(n) lookup. – Blorgbeard Jun 08 '15 at 01:17
  • Yes, your code is ok ! What error does it give ? Can you provide sample values and expected output ? – Marshal Jun 08 '15 at 01:18
  • The only problem could be mismatched spaces around `==` :) . Not really sure what are you looking for... – Alexei Levenkov Jun 08 '15 at 01:20
  • Thank you Blorgbeard. Whether Tuple as dictionary key will allow adding unique combination of string,long as key? – Jameer Basha Jun 08 '15 at 01:20
  • It is allowing duplicate combination of key value pair – Jameer Basha Jun 08 '15 at 01:21

2 Answers2

4

You can also use HashSet, which doesn't have values, but works as you need.

HashSet< Tuple<string, long> > KPSet = new HashSet< Tuple<string, long> >(); 
...
if(KPSet.Contains(p))
{
    ...
}
nsamsonau
  • 325
  • 1
  • 12
  • Here 'p' is a unique combination of key and value or it works only on unique key – Jameer Basha Jun 08 '15 at 01:23
  • In this case the key is the combination of string and Int64. So pairs {64, "abc"}, {64, "def"}, {22, "abc"} will be considered different. – nsamsonau Jun 08 '15 at 01:25
  • It should be actually otherwise :-) {"abc",64}, {"abc","22"},{"xyz",64},{"xyz",22} - Is that ok? – Jameer Basha Jun 08 '15 at 01:27
  • Yes, they all are different keys. – nsamsonau Jun 08 '15 at 01:29
  • It is allowing duplication combination {"abc",64}, {"abc",64} :( – Jameer Basha Jun 08 '15 at 01:33
  • What do you mean it is? If you add two identical keys, only one instance will be kept in the set. – nsamsonau Jun 08 '15 at 01:41
  • if(!KpSet.Contains(p)) - condition is true in case {"abc",64} already exists and I try to add the same – Jameer Basha Jun 08 '15 at 01:50
  • KeyValuePair.GetHashCode() returns the hash code of the key. This approach will not work at all. You would need a version of KeyValuePair that combines its key and value for hashing and comparison. – glenebob Jun 08 '15 at 01:51
  • That said, HashSet IS what you want, you just need a different class/struct for the elements. – glenebob Jun 08 '15 at 01:52
  • I just did test it. Changes to Value have no effect on GetHashCode() for me. – glenebob Jun 08 '15 at 01:56
  • @glenebob Now, test using HashSet. Again, it does work with KeyValuePair. – nsamsonau Jun 08 '15 at 01:57
  • Ah right, it does work, because apparently comparison is effected by changes to Value, while hash value is not. That defeats the purpose of the hash table; depending on Key variability, it could be less efficient than a List<>. – glenebob Jun 08 '15 at 02:09
  • Please suggest me, what should I use now? – Jameer Basha Jun 08 '15 at 02:21
  • @JameerBasha my examples works fine. You could try to change *KeyValuePair* to *Tuple* to get some performance efficiency. However, both ways are technically correct. – nsamsonau Jun 08 '15 at 02:28
  • 1
    @glenebob http://stackoverflow.com/questions/8952003/how-does-hashset-compare-elements-for-equality As answered in the question, HashSet compares using **both** GetHashCode() **and** key.Equals(). – nsamsonau Jun 08 '15 at 02:33
  • Tuple<> does appear to use all values in its hash function, so it will work as designed in a HashSet. @user3290260, using a hash table for items that do not produce reasonable hash codes is simply poor design. – glenebob Jun 08 '15 at 04:42
  • @user3290260, if you update your answer to use Tuple, with a comment about correct hashing vs KeyValuePair, I'll remove my down-vote. – glenebob Jun 08 '15 at 04:44
1

For easy-use and best performance I would like to suggest use combination of Dictionary and HashSet :

var KPDict = new Dictionary<string, HashSet<long>>();

Then it will provides you O(1)+O(1) lookup complexity and easy check of value:

if (KPDict.ContainsKey(keyp) && KPDict[keyp].Contains(valuep)) {
    //do some actions
}
else{
    //some logic in case keyp, valuep pair not found in KPDict
}
Volodymyr
  • 1,209
  • 1
  • 15
  • 26
  • dictionary has no sort, data can not be inserted at specific index etc - bad solution – PernerOl Jun 10 '16 at 15:51
  • @PernerOl bad solution for what? – Volodymyr Jun 10 '16 at 20:37
  • The user was asking for a possibility to check the Key/values in a list with key value pair. As already mentioned, a dictionary is no appropriate alternative for a list, because it misses several things like sort (you would need foreach loops, or lambdas), or inserting at at specific index. as you don't know, what else the list will be used for, it's illogic to say 'use a dictionary instead' - the user will have his reasons he chose a list and not a dictionary. if he would like to know, what kind of datatype performs best, he probably would have asked for it, don't you think? ;) – PernerOl Jun 11 '16 at 00:38
  • 1
    @PernerOl From the question, "I can't use dictionary since I need to have unique combination of key and value ..", which suggests that the OP has no issue with using a `Dictionary`, other than that it wouldn't allow multiple values with the same key. You are assuming a lot of things in your comments that you can't know. – MicroVirus Jun 11 '16 at 00:59