Home > Software design >  double list in return statement. need explanation in python
double list in return statement. need explanation in python

Time:09-23

So I was trying to complete this kata on code wars and I ran across an interesting solution. The kata states:

"Given an array of integers, find the one that appears an odd number of times. There will always be only one integer that appears an odd number of times."

and one of the solutions for it was:

def find_it(seq):
    return [x for x in seq if seq.count(x) % 2][0]

My question is why is there [0] at the end of the statement. I tried playing around with it and putting [1] instead and when testing, it passed some tests but not others with no obvious pattern.

Any explanation will be greatly appreciated.

CodePudding user response:

That list comprehension yields a sequence of values that occur an odd number of times. The first value of that sequence will occur an odd number of times. Therefore, getting the first value of that sequence (via [0]) gets you a value that occurs an odd number of times.

Happy coding!

CodePudding user response:

That code [x for x in seq if seq.count(x) % 2] return the list which has 1 value appears in input list an odd numbers of times.
So, to make the output as number, not as list, he indicates 0th index, so it returns 0th index of list with one value.

CodePudding user response:

The first brackets are a list comprehension, the second is indexing the resulting list. It's equivalent to:

def find_it(seq):
    thelist = [x for x in seq if seq.count(x) % 2]
    return thelist[0]

The code is actually pretty inefficient, because it builds the whole list just to get the first value that passed the test. It could be implemented much more efficiently with next a generator expression (like a listcomp, but lazy, with the values produced exactly once, and only on demand):

def find_it(seq):
    return next(x for x in seq if seq.count(x) % 2)

which would behave the same, with the only difference being that the exception raised if no values passed the test would be IndexError in the original code, and StopIteration in the new code, and it would operate more efficiently by stopping the search the instant a value passed the test. Further optimizations are possible (if the input begins [1, 1, 1, 1, ...] and the total number of 1s is even, this code needlessly rechecks the count for all of them), but they'd lose the brevity of a listcomp/genexpr.

  • Related