2008-11-27 13 views
9

En C++ menudo hacer algo como esto:¿Cuál es el equivalente de map <int, vector <int>> en Python?

typedef map<int, vector<int> > MyIndexType; 

Donde luego usarlo como esto:

MyIndexType myIndex; 
for(... some loop ...) 
{ 
    myIndex[someId].push_back(someVal); 
} 

Si no había ninguna entrada en el mapa del código insertará un nuevo vector vacío y luego anexarlo

En Python se vería así:

myIndex = {} 

for (someId,someVal) in collection: 
    try: 
     myIndex[someId].append(someVal) 
    except KeyError: 
     myIndex[someId] = [someVal] 

El intento excepción es un poco feo aquí. ¿Hay alguna manera de indicarle al diccionario un tipo de objeto para insertar cuando se encuentra un KeyError en el momento de declaración del diccionario?

+0

Debe buscar en multimap <> para su código C++. – SoapBox

+0

Un multimapa no es necesariamente la estructura de datos correcta aquí. Anidar un vector dentro de un mapa está bien. –

+0

De acuerdo: un multimap no retendría el orden de inserción como map > would. – Alastair

Respuesta

15

que desea utilizar:

from collections import defaultdict 
myIndex = defaultdict(list) 
myIndex[someId].append(someVal) 

biblioteca estándar defaultdict objects.

Ejemplo de uso de la documentación de Python:

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] 
>>> d = defaultdict(list) 
>>> for k, v in s: 
     d[k].append(v) 

>>> d.items() 
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])] 
10

Algo como esto quizá:

myIndex = {} 
for (someId,someVal) in collection: 
    myIndex.setdefault(someId, []).append(someVal) 
+0

Esto es fundamentalmente una mejor manera de hacer las cosas que la respuesta de ddaa. – Jerub

+0

@Jerub: No estoy de acuerdo. Usar un valor por defecto es mucho más fácil de leer y tiene la ventaja de que no crea y destruye inmediatamente una nueva lista vacía incluso cuando no agrega una nueva clave (aunque en la práctica es un poco más lenta para las listas, aunque puede ser importante para algunos tipos)) – Brian

+0

Estoy de acuerdo.setdefault() es el camino a seguir. –

0

¿Qué tal esto? Puede que no sea óptimo para el rendimiento, pero creo que es "lo más simple que podría funcionar".

myIndex = {} 

for (someId,someVal) in collection: 
    if someId not in myIndex: 
     myIndex[someId] = [] 
    myIndex[someId].append(someVal) 
+0

En este momento está haciendo 2 búsquedas. Uno más de lo necesario. –

+0

Esto se llama "mirar antes de saltar" (LBYL). Más pythonic es EAFP (google it :-)). En este caso: Proveedores: MyIndex [someID] .Append (someVal) excepto KeyError: MyIndex [someID] = [] someVal Por supuesto, en estos días tenemos defaultdict que es aún mejor :-) –

+0

la última línea del ejemplo debería leer myIndex [someId] .append (someVal) Tenga en cuenta la 'a' minúscula en 'append' –

2

sólo para completar la respuesta por Alastair: También existe la obtener equivalente de setdefault, que se llama obtener (y no getDefault, como se podría pensar):

myIndex = {} 
someId = None 
myList = myIndex.get(someId, []) # myList is [] now 
1

Desde Python 2.5 y en puede obtener el comportamiento de setdefault o usar defaultdict implementando

__missing__(k) 

como en la nota 10 here.

Cuestiones relacionadas