0

I am looking for a quick way to find if hashtable (string to byte array) collection values contains a given value, i can't use the given contains as it will compare the array object not its values.

i don't mind using linq / extension / implementing contains as long as it is short.

i have tried:

byte[] givenArr = new[]{1,2,3,4}; //(a given arr)
bool contains=false;
Hashtable table;
foreach(var val in table.values)
  if (CompareBytesFunction((byte[])val,givenArr))
      contains=true;

where compare bytes is a function to compare the 2 given byte arrays, i feel this is not the right approach. there might be a simpler way to get this without the helper method.

josh
  • 15
  • 5

2 Answers2

2

Even though it's pretty much against the concept of Hashtables which should be searched by key, you can use such code:

//suppose this is the byte array you're looking for:
byte[] b = new byte[] { 1, 3, 5 };

bool exists = myHashtable.Values.OfType<byte[]>().
    ToList().Exists(c => c.SequenceEqual(b));
Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
  • 1
    why you are calling `ToList` after `Cast` and `OfType` ? – Selman Genç Mar 30 '14 at 13:28
  • Simpler version : `myHashtable.Values.Cast().ToList().Exists(c => c.SequenceEqual(b));` – Alexandre Pepin Mar 30 '14 at 13:32
  • Great, exactly what i needed, also protects me from exception in case table was modified in the process. (my solution will throw exception in such a case) – josh Mar 30 '14 at 13:33
  • @Selman22 was able to optimize a bit, but `IEnumerable` doesn't have the `.Exists()` method that I originally wanted so I fear one `.ToList()` is still needed. :( – Shadow The GPT Wizard Mar 30 '14 at 13:34
  • @josh This solution will also throw an exception if another thread modifies the table. – Alexandre Pepin Mar 30 '14 at 13:37
  • @Alexandre adding `lock()` should solve this issue in case of multi threading, isn't it? – Shadow The GPT Wizard Mar 30 '14 at 13:38
  • @AlexandrePepin are you sure ? i think once you made it a list - its thread safe .. no ? – josh Mar 30 '14 at 13:40
  • Yes once it is a list, it is thread safe. The problem is when calling `ToList()`. That method is not thread safe. All `IEnnumerable` methods are not thread safe. See more info [here](http://stackoverflow.com/questions/11103779/are-ienumerable-linq-methods-thread-safe) – Alexandre Pepin Mar 30 '14 at 13:53
  • @AlexandrePepin what you mean is that if the list is changed while `.ToList()` or `.OfType()` are executing, error will happen? This makes sense, but won't `lock()` solve this? To this day I worked a bit with multi threading and always used only lock() around critical sections. – Shadow The GPT Wizard Mar 30 '14 at 13:54
  • No, while calling `ToList()`, the list is not changed. It iterates on it to create a new list. If you changed your list while it is iterating, it will crash. And yes as you said, locking your operation will solve this – Alexandre Pepin Mar 30 '14 at 13:56
  • @josh so to sum this up, to play it safe in multi threaded environment, add a class member/field `object locker = new object()` if you still doesn't have one and just add `lock(locker) {` wrapper around the block of code I gave. – Shadow The GPT Wizard Mar 30 '14 at 14:05
  • Simple solution. But if the array size is big and the hashtable is big, then this would run rather slow. Alternative strategy is to make a hash function that hashes the byte array. The hashtable should then contain hash values of byte arrays. – Kunukn Mar 30 '14 at 17:44
  • @Kunukn true and I started the answer with "it's pretty much against the concept of Hashtables". Guess efficiency isn't the goal for the OP and sometimes it's indeed not crucial, what you suggest will work but means complicating the code and possibly creating more pitfalls. – Shadow The GPT Wizard Mar 30 '14 at 18:39
  • Efficiency is not the goal of the OP, but I bet that being inefficient is not a goal either. Consider `bool exists = myHashtable.Values.OfType().Any(c => c.SequenceEqual(b));` – Kris Vandermotten Jun 02 '21 at 09:20
  • @KrisVandermotten fair suggestion, I think I simply didn't know about the `.Any()` method back when writing this answer. To be fair, your suggestion is enough for a new answer, feel free to post it, writing something like "tweak of [this other answer], you can do it like this...", this will give you some well earned rep and maybe even a badge. :-) – Shadow The GPT Wizard Jun 02 '21 at 12:36
0

You should probably implement an IEqualityComparer that can hash and compare byte[]. Then you can just use the normal hashtable methods.

usr
  • 168,620
  • 35
  • 240
  • 369