"Ernst-Ludwig Brust" <se********@online.dewrites:
Given 2 Number-Lists say l0 and l1,
count the various positiv differences between the 2 lists
the following part works:
dif=[abs(x-y) for x in l0 for y in l1]
da={}
for d in dif: da[d]=da.get(d,0)+1
i wonder, if there is a way, to avoid the list dif
You can iterate over any iterable. A generator is iterable; and you
can (among other ways) create a generator with a generator
expression.
Fortunately, you already know how to write any generator expression:
it's the same as a list comprehension, but without the square
brackets.
So, instead of making a list of differences and iterating over it::
>>seq_a = [15, 17, 26]
seq_b = [14, 17, 22]
diffs = [abs(a - b) for a in seq_a for b in seq_b]
diff_accumulator = {}
for diff in diffs:
... diff_accumulator[diff] = diff_accumulator.get(diff, 0) + 1
...
>>diff_accumulator
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 7: 1, 9: 1, 12: 1}
you can skip the intermediate list creation and iterate over the
generator made by an identical generator expression::
>>seq_a = [15, 17, 26]
seq_b = [14, 17, 22]
diff_accumulator = {}
for diff in (abs(a - b) for a in seq_a for b in seq_b):
... diff_accumulator[diff] = diff_accumulator.get(diff, 0) + 1
...
>>diff_accumulator
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 7: 1, 9: 1, 12: 1}
If you wanted to avoid starting the dict empty and writing the ‘for’
loop yourself, you could even create your dict from a generator (the
dict type can make a new dict from any key+value iterable) with the
help of the standard library ‘itertools’ module::
>>import itertools
seq_a = [15, 17, 26]
seq_b = [14, 17, 22]
diffs = [abs(a - b) for a in seq_a for b in seq_b]
diff_accumulator = dict(
... (diff, len(list(items)))
... for (diff, items) in itertools.groupby(diffs)
... )
>>diff_accumulator
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 7: 1, 9: 1, 12: 1}
This also, of course, benefits from the earlier approach to iterate
over the diffs directly instead of an intermediate list::
>>import itertools
seq_a = [15, 17, 26]
seq_b = [14, 17, 22]
diff_accumulator = dict(
... (diff, len(list(items)))
... for (diff, items) in itertools.groupby(
... abs(a - b) for a in seq_a for b in seq_b
... )
... )
>>diff_accumulator
{0: 1, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1, 7: 1, 9: 1, 12: 1}
So, generator expressions can be a powerful way to clarify the purpose
of a section of code. They can be over-used, though: don't use them
unless they actually *do* clarify the code; sometimes an explicit
looping construct is clearer.
--
\ “Like the creators of sitcoms or junk food or package tours, |
`\ Java's designers were consciously designing a product for |
_o__) people not as smart as them.” —Paul Graham |
Ben Finney