Reputation: 49
I am looking for a nicer way to clean up this clunky nest for-loop that I have.
names = ['name1', 'name2', 'name3', ...]
values = [[1, 2, 3, ...], [10, 20, 30, ...], [100, 200, 300, ...]]
for i in range(len(values[0])):
for name, value in zip(names, values):
print(name, value[i])
Output:
name1 1
name2 10
name3 100
name1 2
name2 20
name3 200
name1 3
name2 30
name3 300
...
The above snippet gives the desired output but is certainly not very pythonic.
Upvotes: 1
Views: 82
Reputation: 5549
This function might be helpful in general:
def nested_indices(lol, indices_so_far=None):
indices_so_far = indices_so_far or []
if not isinstance(lol, list):
yield indices_so_far
return
for i in range(len(lol)):
for ni in nested_indices(lol[i], indices_so_far + [i]):
yield ni
Now you can do this sort of thing:
for i,j in nested_indices(values):
print(names[i], values[i][j])
Upvotes: 0
Reputation: 338326
While you could do this:
# assuming your "values" list can be generated dynamically
def values(how_many):
for i in range(1, how_many + 1):
yield [i * 10 ** pow for pow in range(0, how_many)]
names = ['name1', 'name2', 'name3']
[name + ' ' + str(val) for vals in values(len(names)) for name, val in zip(names, vals)]
which generates this list of values:
['name1 1', 'name2 10', 'name3 100', 'name1 2', 'name2 20', 'name3 200', 'name1 3', 'name2 30', 'name3 300']
I don't think that pressing it all into a single list comprehension is inherently more pythonic. It's a neat little trick, but it's not an improvement.
Keep your nested loops, they are straight-forward, readable and won't cause your future self a headache.
Assuming your values list is static, like your sample shows, I don't think this is much of an improvement either.
names = ['name1', 'name2', 'name3']
values = [[1, 2, 3], [10, 20, 30], [100, 200, 300]]
[name + ' ' + str(value[i]) for i in range(len(values[0])) for name, value in zip(names, values)]
Upvotes: 2