Generating a position lookup function for an arbitrary list of integers

You really need a hash-table. Your method with Which statement won't scale to a large number of elements in a list, since Which does a linear look-up. Here are some possibilities.

DownValues and SubValues

Create one via DownValues, like @belisarius demonstrated in his answer.

Dispatch-ed replace rules

Another way (a little less stateful, since rules won't be attached to a symbol) is to use Dispatch-ed rules, like so:

lst = {2, 0, 11, 9, 20, 1, 16} 

rules = Dispatch@Thread[# -> Range[Length[#]]] &[lst]

Then, for example,

11 /. rules

(*  3  *)

System`Utilities`HashTable

Use System`Utilities`HashTable, like so:

h = System`Utilities`HashTable[];
MapThread[System`Utilities`HashTableAdd[h, ##] &, {lst, Range[Length[lst]]}]; 

where now you can extract the position for a given element as

System`Utilities`HashTableGet[h,11]

(* 3 *)

More details on the use of this hash table can be found in this excellent answer by Oleksandr.

Using (sparse) arrays

Sometimes you may simply use arrays, or possibly sparse arrays, as a hash table. This is particularly useful for integer lists where integer values are not too large (although sparse arrays will handle also large values). I will demonstrate this by defining a new data type storage, like so:

Clear[makeStorage, storage];
makeStorage[lst_, $threshold_: 10^5] :=
  With[{len = Max[lst] - Min[lst] + 1},
    Module[{arr =  
       If[len < $threshold, 
              Table[0, {len}], 
              SparseArray[{0}, {len}, 0]
       ]}, 
      arr[[lst - Min[lst] + 1]] = Range[Length[lst]];
      storage[arr, Min[lst]]]];

storage /: getPosition[storage[arr_, min_], elem_] := arr[[elem - min + 1]];

Here is how you use it:

st = makeStorage[lst];

getPosition[st,11]

(* 3 *)

The advantage of this method is that when plain (non-sparse) arrays can be used,this will be the fastest one. The disadvantage is that using plain arrays is very memory-wasteful, so you trade memory for speed. You may wish to also define a bulk element extractor method

storage /: getPositions[storage[arr_, min_], elems_List] := 
    arr[[elems - min + 1]];

since this will be very efficient. You can see this approach put to practical use in this answer, where you can also see how much speed-up one can get by using it. I also put it (in a slightly different form) to use in this answer, where it was inside Compile.


I think the most straightforward way is:

MapIndexed[(f[#1] = #2[[1]]) &, numlist]

{#, f@#} & /@ numlist // TableForm
(*
7   1
81  2
96  3
*)

Edit

If you need to do this for an unknown number of lists and functions in your program, you could go:

defFun[g_Symbol, l_List]:= MapIndexed[(g[#1] = #2[[1]]) &, l]

Usage

ClearAll@h;
defFun[h, k = Table[Fibonacci@i, {i, 2, 10}]]
{#, h@#} & /@ k // TableForm
(*
1   1
2   2
3   3
5   4
8   5
13  6
21  7
34  8
55  9
*)

Nowadays, one can just build an Association[]. Using Leonid's example:

assoc = Association[MapIndexed[# -> #2[[1]] &, {2, 0, 11, 9, 20, 1, 16}]];

or as Carl notes, you can use PositionIndex[] to build the required association:

assoc = First /@ PositionIndex[{2, 0, 11, 9, 20, 1, 16}];

assoc[11]
   3

If you need to get the values for two or more keys, use Lookup[]:

Lookup[assoc, {11, 9}]
   {3, 4}