Dictionary use instead of dynamic variable names in Python

耗尽温柔 提交于 2019-12-02 01:14:08

You are definitely correct that it is almost always a bad idea to try and create "dynamic variables" in a scope. Dictionaries usually are the answer to build up a collection of objects over time and reference back to them...

I don't fully understand your application and format, but in general to define and use your dictionary it would look like this:

trucks = {}
trucks['0300'] = ['a']
trucks['0300'].append('c')
trucks['0300'].extend(['c','d'])

aTruck = trucks['0300']

Now since every one of these should be a list of your strings, you might just want to use a defaultdict, and tell it to use a list as default value for non existant keys:

from collections import defaultdict

trucks = defaultdict(list)
trucks['0300']
# []

Note that even though it was a brand new dict that contained no entries, the 'truck_0300' key still return a new list. This means you don't have to check for the key. Just append:

trucks = defaultdict(list)
trucks['0300'].append('a')

A defaultdict is probably what you want, since you do not have to pre-define keys at all. It is there when you are ready for it.

Getting key for the max value

From your comments, here is an example of how to get the key with the max value of a dictionary. It is pretty easy, as you just use max and define how it should determine the key to use for the comparisons:

d = {'a':10, 'b':5, 'c':50}
print max(d.iteritems(), key=lambda (k,v): v)
# ('c', 50)
d['c'] = 1
print max(d.iteritems(), key=lambda (k,v): v)
# ('a', 10)

All you have to do is define how to produce a comparison key. In this case I just tell it to take the value as the key. For really simply key functions like this where you are just telling it to pull an index or attribute from the object, you can make it more efficient by using the operator module so that the key function is in C and not in python as a lambda:

from operator import itemgetter
...
print max(d.iteritems(), key=itemgetter(1))
#('c', 50)

itemgetter creates a new callable that will pull the second item from the tuple that is passed in by the loop.

Now assume each value is actually a list (similar to your structure). We will make it a list of numbers, and you want to find the key which has the list with the largest total:

d = {'a': range(1,5), 'b': range(2,4), 'c': range(5,7)}
print max(d.iteritems(), key=lambda (k,v): sum(v))
# ('c', [5, 6])

If the number of keys is more than 10,000, then this method is not viable. Otherwise define a dictionary d = {} and do a loop over your lines:

key = line[:4]
if not key in d.keys():
    d[key] = []
d[key] += [somevalue]

I hope this helps.

Here's a complete solution from string to output:

from collections import namedtuple, defaultdict

# lightweight class
Truck = namedtuple('Truck', 'weights spacings')

def parse_truck(s):
    # convert to array of numbers
    numbers = [int(''.join(t)) for t in zip(s[::2], s[1::2])]

    # check length
    n = numbers[0]
    assert n * 2 == len(numbers)
    numbers = numbers[1:]

    return Truck(numbers[:n], numbers[n:])

trucks = [
    parse_truck("031028331004"),
    ...
]

# dictionary where every key contains a list by default
trucks_by_spacing = defaultdict(list)

for truck in trucks:
    # (True, False) instead of '10'
    key = tuple(space > 6 for space in truck.spacings)
    trucks_by_spacing[key].append(truck)

print trucks_by_spacing

print trucks_by_spacing[True, False]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!