1

I have lines = ["222,333", ...] How to rewrite following:

res = 0
result = []
for line in lines:
   body, exp = line.split(',')
   logr = math.log(int(body), int(exp))
   if logr > res:
       res = logr
       result = [int(body), int(exp)]

into one-liner?

I am trying something like

result = [math.log(int(d.split(',')[0]), int(d.split(',')[1])) for d in lines]

But after I do that, I'm stuck. How to compare my math.log to previous result and if it is bigger, write it to some variable?

I expect the output to be "333,444", or something similar.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
Igor Hwang
  • 72
  • 7
  • I think your original version is a lot clearer. LC isn't really the appropriate construct for reduce operations, IMHO. – ggorlen May 05 '19 at 18:34

1 Answers1

3

A one-liner for result, and a one-liner for res:

result = max([[*map(int,d.split(','))] for d in lines], key=lambda p: math.log(*p))
res = math.log(*result)

tada

What magic is this?

One point to realise is that result will end up being only one list of length two: [body, exp]. And this list is decided by logr > res—a key to sort by—implying the use of min, sorted, max, or similar.

The issue with immediately evaluating the log, as demonstrated in the attempt in the question, is that we lose the values obtained from split(', '). But we need these values for result! Instead, keep the values, determine the correct pair first, and evaluate the log afterwards.

Now down to the one-liners. The first part of the comprehension is fairly straightforward.

[[*map(int,d.split(','))] for d in lines]

This creates a list of lists of parsed lines.

["111,222", "333,444", "555,666"]  # before (lines)
[[111, 222],
 [333, 444],
 [555, 666]]    # after (list comp.)

We then select the pair which has the highest log. In other words, we take the max, comparing by a key of key=lambda p: math.log(*p) (i.e. compare by the log).

(In case you were wondering what the asterisk does, it unpacks the given iterable (see What does the star operator mean? for more info). In this particular case, math.log(*p) is the same as math.log(p[0], p[1]).)

Once we've selected our result, we throw it into math.log again to compute res.

And all ends well.

TrebledJ
  • 8,713
  • 7
  • 26
  • 48
  • 1
    That's..... wow. I didn't even think of inserting lambda function in list comprehension and then surround it with `max` argument! Thank you very much, I literally was stuck for more than day on that! – Igor Hwang May 06 '19 at 05:06