0

I have a hash table that contains values of a^j. j is the key and a^j is the value. I am now calculating another value a^m. I basically want to see if a^m is in the hash table. I used the ContainsValue fn. to find the value. How would i go about finding out the key of the value?

Here is a little snippet of where i want to implement the search for the value.

    Dictionary<BigInteger, BigInteger> b = new Dictionary<BigInteger, BigInteger>();
     ***add a bunch of BigIntegers into b***
    for(int j=0; j < n; j++)
    {
       z =  q* BigInteger.ModPow(temp,j,mod);
       ***I want to implement to search for z in b here****
    }

Does this change anything? the fact that i am searching while inside a for loop?

Nook
  • 179
  • 1
  • 3
  • 9
  • 1
    Y u no use `Dictionary`? – NullUserException Sep 21 '11 at 05:20
  • I do not know how to use Dictionary, and i already figured out how to do what i need to with a hash table, at least for the most part. would it be easy to convert my hash table of BigIntegers into Dictionary? – Nook Sep 21 '11 at 05:22
  • And if your keys are the exponent, why don't you just check if the key `m` [is present](http://msdn.microsoft.com/en-us/library/system.collections.hashtable.containskey.aspx)? – NullUserException Sep 21 '11 at 05:24
  • See: http://stackoverflow.com/questions/301371/why-dictionary-is-preferred-over-hashtable-in-c – NullUserException Sep 21 '11 at 05:24
  • @ NullUser Well i have already created a hash table that has all the values (j,a^j). I then use a for loop to calculate the number z=r* BigInteger.ModPow(a,j,mod). While in the for loop, 0 – Nook Sep 21 '11 at 05:30

4 Answers4

1

The fastest way is probably to iterate through the hashtable's DictionaryEntry items to find the value, which in turn gives you the key. I don't see how else to do it.

kprobst
  • 16,165
  • 5
  • 32
  • 53
1

Firstly, you should absolutely be using Dictionary<TKey, TValue> instead of Hashtable - if you're using BigInteger from .NET 4, there's no reason not to use generic collections everywhere you can. Chances are for the most part you'd see no difference in how it's used - just create it with:

Dictionary<BigInteger, BigInteger> map = 
    new Dictionary<BigInteger, BigInteger>();

to start with. One thing to watch out for is that the indexer will throw an exception if the key isn't present in the map - use TryGetValue to fetch the value if it exists and a bool to say whether or not it did exist.

As for finding the key by value - there's no way to do that efficiently from a Dictionary. You can search all the entries, which is most easily done with LINQ:

var key = map.Where(pair => pair.Value == value)
             .Select(pair => pair.Key)
             .First();

but that will iterate over the whole dictionary until it finds a match, so it's an O(n) operation.

If you want to do this efficiently, you should keep two dictionaries - one from a to a^j and one from a^j to a. When you add an entry, add it both ways round. Somewhere on Stack Overflow I've got some sample code of a class which does this for you, but I doubt I'd be able to find it easily. EDIT: There's one which copes with multiple mappings here; the "single mapping" version is in the answer beneath that one.

Anyway, once you've got two dictionaries, one in each direction, it's easy - obviously you'd just lookup a^m as a key in the second dictionary to find the original value which created it.

Note that you'll need to consider whether it's possible for two original keys to end up with the same value - at that point you obviously wouldn't be able to have both mappings in one reverse dictionary (unless it was a Dictionary<BigInteger, List<BigInteger>> or something similar).

Community
  • 1
  • 1
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • well the value a^m was just what i put in for the question. In the program it is q = j* BigInteger.ModPow(a(inverse),j,mod) and the for loop goes from 0 – Nook Sep 21 '11 at 05:37
  • I think your previous answer is here: http://stackoverflow.com/questions/255341/getting-key-of-value-of-a-generic-dictionary – Simon Mourier Sep 21 '11 at 05:40
  • @Nook: That's irrelevant really - basically you've got keys and they map to values. If you want an *efficient* way of going the other way, you'll need to build another mapping. If you don't care about this lookup being O(n), you can just iterate instead. – Jon Skeet Sep 21 '11 at 06:01
0
private object GetKeyByValue(object searchValue)
{
    foreach (DictionaryEntry entry in myHashTable)
    {
        if (entry.Value.Equals(searchValue))
        {
            return entry.Key;
        }
    }

    return null;
}
CharithJ
  • 46,289
  • 20
  • 116
  • 131
0

Edit: Changed to use Dictionary<TKey, TValue>

Dictionary<TKey, TValue> is an IEnumerable<KeyValuePair<TKey, TValue>>. If you do a foreach over it directly, you can get both the key and value for each entry.

class SomeType
{
    public int SomeData = 5;

    public override string ToString()
    {
        return SomeData.ToString();
    }
}

// ...

var blah = new Dictionary<string, SomeType>();
blah.Add("test", new SomeType() { SomeData = 6 });

foreach (KeyValuePair<string, SomeType> item in blah)
{
    if(e.Value.SomeData == 6)
    {
        Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
    }
}

If you have a newer version of the .Net framework, you could use Linq to find your matches, and place them in their own collection. Here's a code sample showing a little bit of Linq syntax:

using System;
using System.Collections;
using System.Linq;

class SomeType
{
    public int SomeData = 5;

    public override string ToString()
    {
        return SomeData.ToString();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var blah = new Dictionary<string, SomeType>();
        blah.Add("test", new SomeType() { SomeData = 6 });

        // Build an enumeration of just matches:

        var entriesThatMatchValue = blah
            .Where(e => e.Value.SomeData == 6);

        foreach (KeyValuePair<string, SomeType> item in entriesThatMatchValue)
        {
            Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
        }

        // or: ...

        // Build a sub-enumeration of just keys from matches:

        var keysThatMatchValue = entriesThatMatchValue.Select(e => e.Key);

        // Build a list of keys from matches in-line, using method chaining:

        List<string> matchingKeys = blah
            .Where(e => e.Value.SomeData == 6)
            .Select(e => e.Key)
            .ToList();
    }
}
Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183
  • I changed from the hash table to dictionary as suggested by...almost everyone. So now would i change how i go about searching for the value,v, in the Dictionary b? and finding the key of v? – Nook Sep 21 '11 at 05:57
  • @Nook: You can still use the solution in this answer, you just get rid of the casts. `Dictionary` is an `IEnumerable>`, whereas `Hashtable` is a plain `IEnumerable` (which returns `object` instances of type `DictionaryEntry`). I'll edit the answer to reflect this change... – Merlyn Morgan-Graham Sep 21 '11 at 05:58
  • Thank you! but i am also wondering what is the best way for me to do it since i am already running a for loop from o – Nook Sep 21 '11 at 06:02
  • @Nook: There's no way to transform it besides an `O(N)` operation on the original table. Associative arrays/hash tables/dictionaries aren't designed to solve that problem... You could build both at the same time, though that wouldn't save you much (maybe nothing at all due to having to deal with both tables repeatedly reallocating during resize at the same time). – Merlyn Morgan-Graham Sep 21 '11 at 06:06
  • @Nook: This question might be interesting - http://stackoverflow.com/questions/268321/bidirectional-1-to-1-dictionary-in-c - Tho all such questions and answers I found just use two dictionaries under the covers. – Merlyn Morgan-Graham Sep 21 '11 at 06:16
  • @Nook: One more thing - I brainstormed trying to create your own solution using a `HashSet`, but that won't work. No matter what, you'll need two hashes for each pair for anything faster than `O(N)` access. This is equivalent to two dictionaries, or an ultra-custom bi-directional dictionary (to deal with double-memory-allocation perf issues). One last idea is if you can safely and efficiently stuff the values into an in-memory DB (like SqLite), you could index both the keys and values columns. This would break on duplicates, tho. – Merlyn Morgan-Graham Sep 21 '11 at 06:24