Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested looping over tuple values in a dictionary with tuple keys python

I have a defaultdict where the key is a 4-tuple (gene_region, species, ontology, length).

Looping over it is simple:

for gene_region, species, ontology, length in result_dict:

However, I'd like to iterate over it in a nested fashion, like this:

for gene_region
    for species
        for ontology
            ...

How do I do this? Is there no other way than collecting the values first? Or using the following dum-dum way:

for gene_region, _, _, _ in result_dict:
    for _, species, _, _ in result_dict:
        ...
like image 566
The Unfun Cat Avatar asked Aug 29 '26 20:08

The Unfun Cat


2 Answers

You'd have to collect all the various key elements into lists, then loop over those (using itertools.product(), preferably). The collecting can be done with zip():

from itertools import product

gene_regions, species_plural, ontologies, lengths = zip(*result_dict)

for gene_region, species, ontology, length in product(gene_regions, species_plural, ontologies, lengths):
    # do something with this combo.

product() produces the same sequence of combinations as if you had nested your loops.

like image 128
Martijn Pieters Avatar answered Sep 01 '26 09:09

Martijn Pieters


I think you could consider recreating your data as nested dictionaries:

>>> result_dict = {}
>>> result_dict[(1, 2, 3, 4)] = "test"
>>> result_dict[(1, 2, 4, 4)] = "test2"
>>> result_dict
{(1, 2, 3, 4): 'test', (1, 2, 4, 4): 'test2'}

>>> result_dict2 = {}
>>> for (a, b, c, d), k in result_dict.iteritems():
...     result_dict2.setdefault(a, {}).setdefault(b, {}).setdefault(c, {})[d] = k
... 
>>> result_dict2
{1: {2: {3: {4: 'test'}, 4: {4: 'test2'}}}}

then you can iterate over the keys on any level:

for _, a in result_dict2.iteritems():
    for _, b in a.iteritems():
        for _, c in b.iteritems():
            for _, d in c.iteritems():
                # do something
like image 33
Roman Pekar Avatar answered Sep 01 '26 08:09

Roman Pekar