简体   繁体   中英

Finding an element of a list when the list is in a dictionary?

This is homework, so I don't expect the answer, just a point in the right direction.

In python I have a dictionary that is like so:

{'bike101': ('Road Bike',
             [('WH139', 2),
              ('TR102', 2),
              ('TU177', 2),
              ('FR101', 1),
              ('FB101', 1),
              ('BB101', 1),
              ('GS101', 1)]),
 'bike201': ('Mountain Bike',
             [('WH239', 2),
              ('TR202', 2),
              ('TU277', 2),
              ('FR201', 1),
              ('FB201', 1),
              ('BB201', 1),
              ('GS201', 1)]),
 'bike301': ('Racing Bike',
             [('WH339', 2),
              ('TR302', 2),
              ('TU377', 2),
              ('FR301', 1),
              ('FB301', 1),
              ('BB301', 1),
              ('GS301', 1)])}

For example 'Racing Bike' is the product name and the list of pairs is (part, amount required), respectively.

I have to write a function that, given the above dictionary and the product name as an argument will then return the key for it and return 'None' if the product name does not exist.

I used:

    return [key for key, value in product_dict.iteritems() if list(value)[0] == string]

And this returned the correct key when tested but I don't know how to make it return 'none' if the product name doesn't exist and I am not sure if this is the best way to do this.'

I can only use the builtin functions in python, any help is greatly appreciated!

Since you're asking for hints, I won't post working code.

Your code is a list comprehension, so it outputs a list. If there is no result, the list will be empty. You can bind the list to a variable, use len() to check its length and return None if it is 0.

Using a list comprehension is perhaps not the most obvious way here since you're not building a list but searching for a single item. Your code is not returning the key but a list of size 1 if the key is found or a list of size 0 if it doesn't exist.

One way to use this to your advantage is to access the first element ( [0] ) of your list comprehension. Then you'll get an IndexError if the list is empty. Surround the list comprehension with a try/except and return None if IndexError is raised.

A list comprehension is for building a list; what you really want here is to find data. That immediately suggests a dictionary, but in this situation the simplest way would be to use loops to simply walk over the data, and try to match the product name.

If you need to do these kinds of lookups often ( I understand this is homework, but let's pretend you were writing this for work ), then it will be better to make a new dictionary that is keyed by the product name directly. I'll show you that solution, which is likely not the solution required by your homework, but perhaps you can figure out how to adapt it to the simpler solution using loops:

# Restructure the dictionary
def invert_dictionary(input):
    out={}
    for bike_number in input.keys():                
        product_name, list_of_parts = input[bike_number]
        if not out.has_key(product_name):
            out[product_name]=[]        
        out[product_name].append((bike_number, list_of_parts))
    return out

new_dict = invert_dictionary(d)
# Returns a list of all bikes that are tagged "Racing Bike"
print new_dict['Racing Bike']

Output:

[('bike301', [('WH339', 2), ('TR302', 2), ('TU377', 2), ('FR301', 1), ('FB301', 1), ('BB301', 1), ('GS301', 1)])]

Study how the loops in this code walk over the data. You will need to do something similar to find the data you need on the original dict.

In one line:

product_dict = {'bike301': ('Racing Bike', [('WH339', 2),('TR302', 2),
                                            ('TU377', 2),('FR301', 1),
                                            ('FB301', 1),('BB301', 1),
                                            ('GS301', 1)
                                            ]
                            ),
                'bike201': ('Mountain Bike', [('WH239', 2),('TR202', 2),
                                              ('TU277', 2),('FR201', 1),
                                              ('FB201', 1),('BB201', 1),
                                              ('GS201', 1)
                                              ]
                            ),
                'bike101': ('Road Bike', [('WH139', 2),('TR102', 2),
                                          ('TU177', 2),('FR101', 1),
                                          ('FB101', 1),('BB101', 1),
                                          ('GS101', 1)
                                          ]
                            )
                }


print dict( (string,k) for k,(name,li) in product_dict.iteritems() if name==string).get(string,None)

I see no advantage to have the items of your dictionary under the form number:(name,a_list)

I think it should be better to define:

product_dict2 = {('bike301','Racing Bike'):[('WH339', 2),('TR302', 2),
                                            ('TU377', 2),('FR301', 1),
                                            ('FB301', 1),('BB301', 1),
                                            ('GS301', 1)
                                            ],
                 ('bike201','Mountain Bike'):[('WH239', 2),('TR202', 2),
                                              ('TU277', 2),('FR201', 1),
                                              ('FB201', 1),('BB201', 1),
                                              ('GS201', 1)
                                              ],
                 ('bike101','Road Bike'):[('WH139', 2),('TR102', 2),
                                          ('TU177', 2),('FR101', 1),
                                          ('FB101', 1),('BB101', 1),
                                          ('GS101', 1)
                                          ]
                 }

Then for your need, you would write:

print dict( (string,numb) for numb,name in product_dict2.iterkeys() if name==string).get(string,None)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM