1

some background

I was setting up some tests for code submitted by users for an extremely simple data science test.

coding "challenges" would be structured like so in a Jupyter Notepook:

li1 = [2,4,3,-2,-1,5,10]
li2 = [5,4,-3,7,8,-5,10,9]
def findMedian(li):
    li.sort()

    # find the median of li...
    # your code below

    listlength = len(li)
    num = listlength//2
    if listlength % 2 == 0:
        return (li[num]+li[num-1])/2
    else:
        return li[num]
if findMedian(li1) == 3:
    print("1 is correct!")
else:
    print("1 is wrong")
if findMedian(li2) == 6:
    print("2 is correct!")
else:
    print("2 is wrong")

Now while this is nice enough I decided I should probably implement something like the following to truly check many cases.

from statistics import median
import random

x = [list(range(random.randint(1,50))) for i in range(1,100)]

print(not any([False if findMedian(i) == median(i) else True for i in x]))

the thing is, using not any() feels wrong, I've been doing it for a while and I feel like I have a little gap in my knowledge...

question

Is there a cleaner way to express my comparisons?

while not any([False if findMedian(i) == median(i) else True for i in x]) does the job, is there a more efficient/pythonic way to express this?

Ironkey
  • 2,568
  • 1
  • 8
  • 30
  • 2
    A quick improvement is to use a generator expression instead of a list comprehension. You can't make as good of use of `any`'s early exit if you're strictly producing the data first (although that's unrelated). Also, using a ternary to evaluate to `True`/`False` is off. Just do `print(not any(findMedian(i) != median(i) for i in x))` – Carcigenicate Nov 08 '20 at 00:50
  • Oh I did not think of that. I would happily accept that edit as an answer, thanks for elaborating! – Ironkey Nov 08 '20 at 00:52
  • 3
    `False if findMedian(i) == median(i) else True` is a really convoluted way to write `findMedian(i) != median(i)`. – user2357112 Nov 08 '20 at 00:54
  • 5
    Also, the not-any-not formulation is a really convoluted way of writing `all(findMedian(i) == median(i) for i in x)`. – user2357112 Nov 08 '20 at 00:55
  • 2
    Gotta love De Morgan's Laws. – Carcigenicate Nov 08 '20 at 00:56
  • Thank you both for explaining that, my sense of logic definitely needs some work! – Ironkey Nov 08 '20 at 00:57

1 Answers1

4

Firstly, the list is unnecessary. Use a generator expression instead, which will be more efficient since it will allow any/all to short-circuit.

Next, False if x == y else True is the same as not x == y, and for most objects including ints, x != y.

Lastly, thanks to De Morgan's laws, you can use all(...) instead of not any(not ...).

all(findMedian(i) == median(i) for i in x)
wjandrea
  • 28,235
  • 9
  • 60
  • 81