Sylvain Page
Sylvain Page

Reputation: 633

Python Find permutable list in a dict list

Given

listOfDict = [{'ref': 1, 'a': 1, 'b': 2, 'c': 3},
              {'ref': 2, 'a': 4, 'b': 5, 'c': 6},
              {'ref': 3, 'a': 7, 'b': 8, 'c': 9}]

Lets' consider a list of permutable integer

[7,8,9]=[7,9,8]=[8,7,9]=[8,9,7]=[9,7,8]=[9,8,7] # (3!)

Each of this list has a unique mapping ref, so how given for (8,7,9) can I get ref=3 ?

Also in real case I might until 10 (a,b,c,d,e,f,g,h,i,j)...

Upvotes: 1

Views: 52

Answers (3)

edvard
edvard

Reputation: 446

Here is a commented solution to your problem. The idea is to compare the sorted list of the values in a, b, c etc with the sorted values in list_of_ints. The sorted values will be the same for all permutations of a given set of numbers.

def get_ref(list_of_ints):
    # Loop through dictionaries in listOfDict.
    for dictionary in listOfDict:
        # Get list of values in each dictionary.
        vals = [dictionary[key] for key in dictionary if key != "ref"]
        if sorted(vals) == sorted(list_of_ints):
            # If sorted values are equal to sorted list of ints, return ref.
            return dictionary["ref"])

By the way, I believe it would be cleaner to structure this data as a dict of dicts in the following way:

dicts = {
    1: {'a': 1, 'b': 2, 'c': 3},
    2: {'a': 4, 'b': 5, 'c': 6},
    3: {'a': 7, 'b': 8, 'c': 9}
}

The code would then be:

def get_ref(list_of_ints):
    for ref, dictionary in dicts.items():
        if sorted(dictionary.values()) == sorted(list_of_ints):
            return ref

Assuming that all integers in the permutations are unique, the code can be simplified further using sets instead of sorted lists.

Upvotes: 1

Mohamed Shahin
Mohamed Shahin

Reputation: 1

Since its a list of dict I can call each dict as it self by using for loop and record the first number on ref

for i in listOfDict:
    ref_num=i["ref"]

and to turn dictunary to list we simply use:

z=list(i.values())

then the last step is to find if its the same input list if so we print/return the ref number

if z[1:]==InputList:
        return ref_num

and the code should be like this:

listOfDict = [
{"ref": 1,
 "a": 1,
 "b": 2,
 "c": 3},
{"ref": 2,
    "a": 4,
    "b": 5,
    "c": 6},
{"ref": 3,
    "a": 7,
    "b": 8,
    "c": 9},]

def find_ref_Num(InputList):
for i in listOfDict:
    ref_num=i["ref"]
    z=list(i.values())
    if z[1:]==InputList:
        return ref_num

print ("your ref number is: "+str(find_ref_Num([7,8,9])))

Upvotes: 0

mozway
mozway

Reputation: 262359

You can generate a dictionary that maps the values as frozenset to the value of ref:

listOfDict = [{'ref': 1, 'a': 1, 'b': 2, 'c': 3},
              {'ref': 2, 'a': 4, 'b': 5, 'c': 6},
              {'ref': 3, 'a': 7, 'b': 8, 'c': 9}]

keys = ['a', 'b', 'c']

out = {frozenset(d[k] for k in keys): d['ref'] for d in listOfDict}
# {frozenset({1, 2, 3}): 1,
#  frozenset({4, 5, 6}): 2,
#  frozenset({7, 8, 9}): 3}

example:

check = frozenset((8,7,9))

out[check]
# 3
but I don't know in advance the name of the other keys!

Then use this approach:

out = {}
for d in listOfDict:
    d2 = d.copy() # this is to avoid modifying the original object
    out[frozenset(d2.values())] = d2.pop('ref')
out

or as a comprehension:

out = dict(((d2:=d.copy()).pop('ref'), frozenset(d2.values()))[::-1]
           for d in listOfDict)

Upvotes: 1

Related Questions