7

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?

2
  • What exactly is the output you are hoping for? Commented Jun 14, 2013 at 18:02
  • @cdhagmann Edited question, expected output is now included Commented Jun 14, 2013 at 18:09

3 Answers 3

6

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)]
6
  • Personally, I feel that using range is not very pythonic, but that's a pretty minor style issue Commented Jun 14, 2013 at 18:06
  • @SlaterTyranus: How is range not Pythonic? Commented Jun 14, 2013 at 18:07
  • like I said, it's a small thing, but seeing range always reminds me of Java and is less functional, but it's really a personal thing. Commented Jun 14, 2013 at 18:08
  • @DavidRobinson Amazing! I realize that i only touched the surface of list comprehensions so far. BTW, good that you used the term allel which i avoided in order not to frighten anybody ;) Commented Jun 14, 2013 at 18:33
  • @KlausWarzecha: Cool! Now that I think of it allele was actually the wrong term (since these are pairs of alleles), I should have used genotype. But I'm glad it answers your question. Commented Jun 14, 2013 at 18:40
1

This should work I suppose.

pops = [2,3,4]
alleles = [('A','A'), ('A', 'a'), ('a','a')]
out = [pop*[allele] for pop, allele in zip(pops,alleles)]
print [item for sublist in out for item in sublist]

I have put the code on CodeBunk so you could run it too.

0
population = 2*[('A', 'A')] + 3*[('A', 'a')] + 4*[('a', 'a')]

or

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

population = 2*[hd] + 3*[het] + 4*[hr]

Not the answer you're looking for? Browse other questions tagged or ask your own question.