5
\$\begingroup\$

I'm moving away from map, reduce and filter in favour of list comprehensions. I like list comps but I feel like this is getting on the unreadable side.

Is this the most idiomatic way of achieving this? Is it easy enough to read?

int_list = [-1,-3,5,7]

absolute_diffs = [max( [abs( int_2 ) - abs( int_1 ) for int_2 in int_list] ) for int_1 in int_list]

print max( absolute_diffs )
\$\endgroup\$
1
  • 1
    \$\begingroup\$ It's not mandatory (unless you are writing code for Google), but the Google Python style guide is a good reference for what readable Python code should look like. And it explicitly forbids nested list comprehensions. \$\endgroup\$
    – Jaime
    Commented Jun 12, 2016 at 7:06

2 Answers 2

6
\$\begingroup\$

A more idiomatic and readable solution would be to use itertools.combinations(list, 2) to take all pairs.

max(abs(a) - abs(b) for a, b in itertools.combinations(int_list, 2))

However, that is O(n2). A smarter O(n) solution would be to subtract the minimum absolute value from the maximum absolute value.

absolutes = [abs(elem) for elem in int_list]
print max(absolutes) - min(absolutes)
\$\endgroup\$
6
  • \$\begingroup\$ I wish I could give you an additional up-vote for the alternative algorithm suggestion. For the oblivious: OP's algorithm runs in O(n²) while 200_success' suggestion runs in O(n). \$\endgroup\$ Commented Jun 12, 2016 at 9:39
  • \$\begingroup\$ Yes @DavidFoerster I've changed my code completely based on the suggested algorithm, much nicer. \$\endgroup\$ Commented Jun 12, 2016 at 11:13
  • \$\begingroup\$ You should explicitly add the algorithm you described, since the OP has mapped the list twice for nothing in his edited question (before the rollback). \$\endgroup\$ Commented Jun 12, 2016 at 13:55
  • \$\begingroup\$ @CasimiretHippolyte I've revised the answer to be explicit. \$\endgroup\$ Commented Jun 12, 2016 at 14:30
  • \$\begingroup\$ I was more thinking about this: l = [abs(elem) for elem in int_list] ; print max(l) - min(l) where absolute values are calculated only once, that was the reason of my previous comment. \$\endgroup\$ Commented Jun 12, 2016 at 14:46
0
\$\begingroup\$

An alternative, purely functional style approach that builds on itertools.combinations too is this:

max(itertools.starmap(operator.sub, itertools.combinations(map(abs, int_list), 2)))
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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