Uso del diccionario en lugar de nombres de variables dinámicas en Python

Tengo un archivo de texto largo con configuraciones de camiones. En cada línea, algunas propiedades de un camión se enumeran como una cadena. Cada propiedad tiene su propio espacio de ancho fijo en la cadena, como por ejemplo:

2 chracters = number of axles 2 characters = weight of the first axle 2 characters = weight of the second axle ... 2 characters = weight of the last axle 2 characters = length of the first axle spacing (spacing means distance between axles) 2 characters = length of the second axle spacing ... 2 characters = length of the last axle spacing 

Como ejemplo:

 031028331004 

se refiere a:

 number of axles = 3 first axle weight = 10 second axle weight = 28 third axle weight = 33 first spacing = 10 second spacing = 4 

Ahora, usted tiene una idea acerca de mi estructura de archivos, aquí está mi problema: me gustaría agrupar estos camiones en listas separadas, y nombrar las listas en términos de espaciamiento de ejes. Digamos que estoy usando un tipo de enfoque booleano, y si el espaciado es menor que 6, el booleano es 1, si es mayor que 6, el booleano es 0. Para aclarar, los posibles resultados en un camión de tres ejes son:

 00 #Both spacings > 6 10 #First spacing  6 01 #First spacing > 6, second < 6 11 #Both spacings < 6 

Ahora, como ves, no hay demasiados resultados para un camión de 3 ejes. Sin embargo, si tengo un camión de 12 ejes, el número de combinaciones “posibles” se vuelve loco. La cuestión es que, en realidad, no vería todas las combinaciones “posibles” de espaciamiento de ejes en un camión de 12 ejes. Hay ciertas combinaciones (no sé cuáles, pero mi objective es resolverlo) con un número mucho menor que el número “posible” de combinaciones.

Me gustaría que el código creara listas y las rellenara con las cadenas que definen las propiedades que mencioné anteriormente si solo existe una combinación de este tipo. Pensé que tal vez debería crear listas con nombres de variables como:

 truck_0300[] truck_0301[] truck_0310[] truck_0311[] 

sobre la marcha. Sin embargo, por lo que leo en SF y otras fonts, esto es muy desalentador. ¿Cómo lo harías usando el concepto de diccionario? Entiendo que los diccionarios son como matrices bidimensionales, con una clave (en mi caso, las claves serían algo como truck_0300, truck_0301, etc.) y un par de valores (de nuevo en mi caso, los valores probablemente sean listas que contienen las cadenas reales que pertenezco al tipo de camión correspondiente), sin embargo, no pude averiguar cómo crear ese diccionario y poblarlo con claves y valores variables.

Cualquier idea sería bienvenida! ¡Gracias un montón!

Definitivamente tienes razón, es casi siempre una mala idea intentar crear “variables dinámicas” en un ámbito. Los diccionarios suelen ser la respuesta para crear una colección de objetos a lo largo del tiempo y hacer referencia a ellos …

No entiendo completamente su aplicación y formato, pero en general para definir y usar su diccionario se vería así:

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

Ahora, ya que cada una de estas debe ser una lista de sus cadenas, es posible que solo desee usar un punto predeterminado y decirle que use una lista como valor predeterminado para las claves que no existen:

 from collections import defaultdict trucks = defaultdict(list) trucks['0300'] # [] 

Tenga en cuenta que aunque era un dict nuevo que no contenía entradas, la tecla ‘truck_0300’ aún devuelve una nueva lista. Esto significa que no tienes que buscar la clave. Sólo agregue:

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

Probablemente lo que desea es un valor predeterminado, ya que no tiene que predefinir las claves en absoluto. Está ahí cuando estés listo para ello.

Obteniendo clave para el valor máximo

De sus comentarios, aquí hay un ejemplo de cómo obtener la clave con el valor máximo de un diccionario. Es bastante fácil, ya que solo usa max y define cómo debería determinar la clave a usar para las comparaciones:

 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) 

Todo lo que tienes que hacer es definir cómo producir una clave de comparación. En este caso solo le digo que tome el valor como clave. Para funciones realmente simples como esta, en las que solo le está diciendo que extraiga un índice o atributo del objeto, puede hacerlo más eficiente usando el módulo del operator modo que la función de la tecla esté en C y no en python como un lambda:

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

itemgetter crea un nuevo invocable que itemgetter el segundo elemento de la tupla que pasa por el bucle.

Ahora suponga que cada valor es en realidad una lista (similar a su estructura). La convertiremos en una lista de números, y usted desea encontrar la clave que tiene la lista con el total más grande:

 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]) 

Si el número de claves es más de 10,000, este método no es viable. De lo contrario, defina un diccionario d = {} y haga un bucle sobre sus líneas:

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

Espero que esto ayude.

Aquí hay una solución completa de cadena a salida:

 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]