Tengo un diccionario con valores en ints, bools, y cadenas y listas y una lista ordenada de claves en la que quiero la lista final de listas. Quiero la salida de modo que donde haya una lista, hagamos combinaciones de eso con valores únicos.
Entrada:
cols = ['region', 'city', 'country', 'valid']
vals = {'city': [10, 20], 'valid': True, 'region': 3, 'country': 'US'}
Salida:
[[3, 10, 'US', True], [3, 20, 'US', True]]
Ahora, si otro campo es una lista, aumentaría las combinaciones.
Entrada:
cols = ['region', 'city', 'country', 'valid']
vals = {'city': [10, 20], 'valid': True, 'region': [3, 4], 'country': 'US'}
Salida:
[[3, 10, 'US', True], [3, 20, 'US', True], [4, 10, 'US', True], [4, 20, 'US', True]]
Buscando la forma más pitónica de lograr esto.
3 respuestas
Utilice itertools.product
:
import itertools
cols = ['region', 'city', 'country', 'valid']
vals = {'city': [10, 20], 'valid': True, 'region': [3, 4], 'country': 'US'}
values = [vals[key] for key in cols]
values = [val if isinstance(val, list) else [val] for val in values]
result = list(itertools.product(*values))
print(result)
# [(3, 10, 'US', True), (3, 20, 'US', True), (4, 10, 'US', True), (4, 20, 'US', True)]
Lectura relacionada:
- lista de comprensiones
- argumento desempaquetado (qué
*values
es haciendo enitertools.product(*values)
)
Puede usar itertools.product
para los campos respectivos como,
Pero antes de hacer product
, debe verificar si es una instancia de int
o str
, en caso afirmativo, luego conviértalos en list
o {{X4} } por el bien de la iteración correcta
>>> vals = {'city': [10, 20], 'valid': True, 'region': 3, 'country': 'US'}
>>>
>>> city = vals['city']
>>> region = vals['region']
>>> country = vals['country']
>>>
>>> if not isinstance(region, (list, tuple)):
... region = [region]
...
>>> if not isinstance(country, (list, tuple)):
... country = [country]
...
>>> list(product(region, city, country, [vals['valid']]))
[(3, 10, 'US', True), (3, 20, 'US', True)]
>>> vals
{'city': [10, 20], 'valid': True, 'region': [3, 4], 'country': 'US'}
>>> from itertools import product
>>> list(product(vals['region'], vals['city'], [vals['country']], [vals['valid']]))
[(3, 10, 'US', True), (3, 20, 'US', True), (4, 10, 'US', True), (4, 20, 'US', True)]
Podrías escribir una función para manejar eso como,
$ cat mkcomb.py
from itertools import product
def mk_comb(keys, vals):
values = [
vals[key] if isinstance(vals[key], (list, tuple)) else [vals[key]]
for key in keys
]
return list(product(*values))
cols = ['region', 'city', 'country', 'valid']
vals1 = {'city': [10, 20], 'valid': True, 'region': 3, 'country': 'US'}
vals2 = {'city': [10, 20], 'valid': True, 'region': [3, 4], 'country': 'US'}
print(mk_comb(cols, vals1))
print(mk_comb(cols, vals2))
Salida:
$ python mkcomb.py
[(3, 10, 'US', True), (3, 20, 'US', True)]
[(3, 10, 'US', True), (3, 20, 'US', True), (4, 10, 'US', True), (4, 20, 'US', True)]
La comprensión de la lista puede hacer el trabajo por usted:
list(itertools.product(*[vals[c] if type(vals[c]) == list else [vals[c]] for c in cols]))
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.