Search code examples
pythonbioinformaticsrosalind

Populate list with tuples


I'm just fiddling with a simulation of (Mendel's First Law of Inheritance).

Before i can let the critters mate and analyze the outcome, the population has to be generated, i.e., a list has to be filled with varying numbers of three different types of tuples without unpacking them.

While trying to get familiar with itertools (I'll need combinations later in the mating part), I came up with the following solution:

import itertools

k = 2
m = 3
n = 4

hd = ('A', 'A')       # homozygous dominant
het = ('A', 'a')      # heterozygous 
hr = ('a', 'a')       # homozygous recessive

fhd = itertools.repeat(hd, k)
fhet = itertools.repeat(het, m)
fhr = itertools.repeat(hr, n)

population = [x for x in fhd] + [x for x in fhet] + [x for x in fhr]

which would result in:

[('A', 'A'), ('A', 'A'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a'), ('A', 'a')]

Is there a more reasonable, pythonic or memory saving way to build the final list, e.g. without generating the lists of for the three types of individuals first?


Solution

  • You could use itertools.chain to combine the iterators:

    population = list(itertools.chain(fhd, fhet, fhr))
    

    Though I would say there's no need to use itertools.repeat when you could simply do [hd] * k. Indeed, I would approach this simulation as follows:

    pops = (20, 30, 44)
    alleles = (('A', 'A'), ('A', 'a'), ('a', 'a'))
    
    population = [a for n, a in zip(pops, alleles) for _ in range(n)]
    

    or perhaps

    allele_freqs = ((20, ('A', 'A')),
                    (30, ('A', 'a')),
                    (44, ('a', 'a')))
    
    population = [a for n, a in allele_freqs for _ in range(n)]