3

I want to use a dictionary as below: Example: {[8, 16]:[[1,2,4,8],8], [16, 24]: [[1,2,3,4,8,12], 12]}

8 and 16 are the two numbers that will be input, and i need to construct a dictionary as above.

Using setdefault, i could create a list for values in dictionary, but not for keys

Below is my code:

#!/usr/bin/env python
"""
        This Program calculates common factors between two Numbers , which 
        is stored on a list and also greatest common factor is also computed.
        All this is stored in a dictionary
        Example: { '[n1, n2]': [[Commonfac1(n1,n2), Commonfac2(n1,n2)....Commonfacn(n1,n2)],GreatestCommonFactor] }
"""
def Factors(number):
        result = []
        for i in range(1, number+1):
                if (number % i) == 0:
                        result.append(i)

        return result

def Common_Factors(n1, n2):
        result = []
        for element in n1:
                if element in n2:
                        result.append(element)

        return result

def greatest_common_factor(common_factors):
        count = 0
        length = len(common_factors)
        current_largest = common_factors[count]
        for i in common_factors:
                count += 1
                if count <= length -1:
                        if current_largest < common_factors[count]:
                                current_largest = common_factors[count]
        return current_largest


def main():
        n1 = 8
        n2 = 16
        result1 = Factors(n1)
        result2 = Factors(n2)

        CF = Common_Factors(result1, result2)

        GCF = greatest_common_factor(CF)

        dict = {}

        dict.setdefault([n1, n2], []).append(CF)
        print dict

if __name__ == '__main__':
        main()

When i run the above program I get below error:

$ python math74.py 
Traceback (most recent call last):
  File "math74.py", line 58, in <module>
    main()
  File "math74.py", line 54, in main
    dict.setdefault([n1, n2], []).append(CF)
TypeError: unhashable type: 'list'

Any hints on how i can achieve above. ?

To clarify more: {[8, 16]:[[1,2,4,8],8], [16, 24]: [[1,2,3,4,8,12], 12]}

8, 16 are two numbers, which will be user input, 1, 2, 4, 8 are it's common Factors and 8 is the Greatest common Factor.

Niranjan M.R
  • 343
  • 1
  • 6
  • 23
  • 8
    Convert your `list` to `tuple` before inserting to the `dict`? – Jon Clements Aug 16 '14 at 19:17
  • 1
    Why would you use a mutable container as a key?? –  Aug 16 '14 at 19:20
  • To build on the comment from Jon Clements, Python's syntax also plays nicely with tuples as dict keys. Consider this example dict: `d = { (1,2) : 3, (10,20) : 30 }`. To access a key, you can then write: `d[1,2]`. – FMc Aug 16 '14 at 19:23
  • Something to think about: what would happen if you did `a = [8,16]`, `d[a] = [[1,2,4,8],8]`, `a.append(32)`? – Adam Smith Aug 16 '14 at 19:23
  • @EdgarAroutiounian It might be useful? I realize why you can't, but just because you can't do it with a hashmap doesn't mean the concept itself would be useless in all situations. – Andreas Vinter-Hviid Aug 16 '14 at 19:37

2 Answers2

5

A list isn't probably what you want, because: 1. A list is mutable. That means it can change (remove/add/modify) its values. For example:

>>> testList = [1,5]
>>> d = {"myList": testL}
>>> d
{'myList': [1, 5]}
>>> testList.append(53)
>>> d
{'myList': [1, 5, 53]}
>>> 

As you can see, a list can be changed and keys need to be unique.
For inmutable array-types, Python has a tuple. Once you defined a tuple, it can't be modified. That means, you may also use it as a key in a directory:

>>> myTuple = (4, 5)
>>> myDict = {myTuple: "here is the value"}
>>> myDict
{(4, 5): 'here is the value'}
>>> myTuple.append(9)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
Matt3o12
  • 4,192
  • 6
  • 32
  • 47
2

As already mentioned, you may most likely want to convert the list into tuple, so that it was hashable.

Another approach, especially useful with some more complicated objects, could be the use of pickle library, which serializes the objects.

An example:

import pickle

my_list = [8, 16]
my_value = 'some_value'
my_dict = {pickle.dumps(my_list): my_value}

my_dict[pickle.dumps([8, 16])]  # This equals to 'some_value'
Radosław Roszkowiak
  • 6,381
  • 3
  • 15
  • 27
  • @rroszkowaik Thanks for the reply, I will look in to pickle. – Niranjan M.R Aug 16 '14 at 19:49
  • Using pickle for that isn't a good idea. Pickle is meant to serialize values and save them on the disk (or elsewhere) so that python can get back its sate (values, etc) when the script is terminated. – Matt3o12 Aug 18 '14 at 06:05
  • Not necessarily. Here is a good example of pickle usage to create dictionary keys: http://stackoverflow.com/questions/4669391/python-anyone-have-a-memoizing-decorator-that-can-handle-unhashable-arguments#answer-4669720. I agree in this case converting to tuple is a way to go, though. – Radosław Roszkowiak Aug 18 '14 at 11:39