1

I have list of around 10,000 elements and for each pair combination of elements from this list I have a number. I need to have all this numbers and combinations in memory to call it by both variants: comb(a,b) or comb(b,a).

However, I don't want to duplicate values in dictionary or something like this, because dict[a][b] = dict[b][a]. Could you advice me a data structure without duplication?

3
  • maybe a set of frozensets? set(frozenset([a,b,comb(a,b)]), ...) Commented Nov 8, 2016 at 18:26
  • Applying filters to a pandas dataframe should do the trick. pandas.pydata.org/pandas-docs/version/0.18.1/generated/… Commented Nov 8, 2016 at 18:28
  • Can you access combinations using indexes instead of using actual values ? for example if you have list a=[1,2,3,4] then instead of finding comb(2,4) can you use comb(1,3) i.e. the indexes ? Commented Nov 8, 2016 at 19:33

3 Answers 3

4

I would suggest you to go with frozenset. More docs: https://docs.python.org/2/library/stdtypes.html#frozenset

So you will have a dict, where frozensets will act as keys(please note that you can't use regular set, since it is mutable and couldn't act as a dictionary key). Frozenset is unordered, so it perfectly fits your needs. The only limitations is that you can't duplicate elements - frozenset is unordered sequence of unique elements.

So your dict will looks like:

pairs = {
frozenset(['a', 'b']): 4
....
}

And a call pairs[frozenset(['a', 'b'])] is equal to pairs[frozenset(['b', 'a'])]

UPD: I was really hurry at first, so made a few typos. Fixed them now :)

Sign up to request clarification or add additional context in comments.

Comments

0
d = {}
d[('a', 'b')] = 12
d[('y', 'z')] = 34

and a function to fetch

def fetch(a, b):
    return d.get((a, b)) if (a, b) in d else d.get((b, a), None)

output:

In [16]:
fetch('b', 'a')
Out[16]:
12

In [17]:
fetch('y', 'z')
Out[17]:
34

In [19]:
fetch('z', 'y')
Out[19]:
34

In [20]:
fetch('m', 'n')

Comments

0

Note: I am assuming that the values in the list are unique and you have flexibility to use indexes of actual values (or you are ready to sacrifice time)

If you really want to save space , i would suggest you to use list of lists to store values for each combination. You do not actually need to store mapping (a,b) -> x.

For example, consider the list:

a = [1,2,3,4]

Suppose Combinations/value pairs are:

(1,2) -> 2, (1,3) -> 3, (1,4) -> 4, (2,3) -> 5, (2,4) -> 6, (3,4) -> 7

The storage for combination/value pair will look like:

comb_value = [[2,3,4],[5,6],[7]]

Retrieval:

Assuming that list a and comb_value are global. (We will dry run the code simultaneously.)

# Consider that x=2 and y=4.
def comb(x,y):
   # if you can use index directly, next 2 lines should be skipped.
   x= find_index(x) # Returns 1. 
   y= find_index(y) # Returns 3.
   if x < y :
      return _comb(x,y) # calling _comb(1,3)
   return _comb(y,x)

# x= 1 and y =3
def _comb(x,y):
   return comb_value[x][y-x-1] # returns comb_value[1][3-1] i.e. 6.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.