Лучший способ найти max и min из двух значений

У меня есть функция, которая пропускает два значения и затем выполняет итерацию по диапазону этих значений. Значения могут быть переданы в любом порядке, поэтому мне нужно найти, какая из них самая низкая. У меня была функция, написанная следующим образом:

def myFunc(x, y):
    if x > y:
        min_val, max_val = y, x
    else:
        min_val, max_val = x, y
    for i in range(min_val, max_val):
    ...

Но чтобы сохранить некоторое пространство на экране, я в конечном итоге изменил его на:

def myFunc(x, y):
   min_val, max_val = sorted([x, y])
   for i in range(min_val, max_val):
   ...

Насколько это плохо? Есть ли лучший способ, что еще одна строка?

Ответ 1

Если вам не понадобится микрооптимизация, я просто к этому

def myFunc(x, y):
    for i in range(*sorted((x, y))):
        ...

Это быстрее, хотя

def myFunc(x, y):
    for i in range(x,y) if x<y else range(y,x):
        ...

minmax.py

def f1(x, y):
    for i in range(min(x, y), max(x, y)):
        pass

def f2(x, y):
    for i in range(*sorted((x, y))):
        pass

def f3(x, y):
    for i in range(x, y) if x<y else range(y, x):
        pass

def f4(x, y):
    if x>y:
        x,y = y,x
    for i in range(x, y):
        pass

def f5(x, y):
    mn,mx = ((x, y), (y, x))[x>y]
    for i in range(x,y):
        pass

тесты (f3 быстрее всех, независимо от порядка)

$ python -m timeit -s"import minmax as mm" "mm.f1(1,2)"
1000000 loops, best of 3: 1.93 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f2(1,2)"
100000 loops, best of 3: 2.4 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f3(1,2)"
1000000 loops, best of 3: 1.16 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f4(1,2)"
100000 loops, best of 3: 1.2 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f5(1,2)"
1000000 loops, best of 3: 1.58 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f1(2,1)"
100000 loops, best of 3: 1.88 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f2(2,1)"
100000 loops, best of 3: 2.39 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f3(2,1)"
1000000 loops, best of 3: 1.18 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f4(2,1)"
1000000 loops, best of 3: 1.25 usec per loop
$ python -m timeit -s"import minmax as mm" "mm.f5(2,1)"
1000000 loops, best of 3: 1.44 usec per loop

Ответ 2

min и max являются вашими друзья.

def myFunc(x, y):
    min_val, max_val = min(x, y), max(x, y)

Изменить. Сравнительная версия min-max снова в простой if. Из-за служебных данных вызова функции min-max принимает 2.5x дольше, чем простой if; см. http://gist.github.com/571049

Ответ 3

Мне нравится sorted. Умный, но не слишком умный. Вот некоторые другие варианты.

def myFunc(min, max):
    if min > max: min, max = max, min

def myFunc(x, y):
    min, max = min(x, y), max(x, y)

def myFunc(x, y):
    min, max = [f(x, y) for f in (min, max)]

Последний, немного глупый, я допускаю.

Ответ 4

Поскольку вопрос OP был задан с использованием x и y в качестве параметров (не lo и hi), я бы пошел (как для скорости, так и для ясности):

def myfunc(x, y):
    lo, hi = (x, y) if x < y else (y, x)

>>> timeit.repeat("myfunc(10, 5)", "from __main__ import myfunc")
[1.2527812156004074, 1.185214249195269, 1.1886092749118689]
>>> timeit.repeat("foo(10, 5)", "from __main__ import foo")
[1.0397177348022524, 0.9580022495574667, 0.9673979369035806]
>>> timeit.repeat("f3(10, 5)", "from __main__ import f3")
[2.47303065772212, 2.4192818561823515, 2.4132735135754046]

Ответ 5

Самый лучший ответ работает как:

def foo(lo, hi):
    if hi < lo: lo,hi = hi,lo

Это ясно, делает точку и не скрывает смысла в кучу дополнительного клея. Это коротко. Это почти наверняка так же быстро, как и любой другой вариант на практике, и он полагается на наименьшее количество умных способностей.

Ответ 6

Некоторые предложения

def myfunc(minVal, maxVal):
    if minVal > maxVal: minVal, maxVal = maxVal, minVal

def myfunc2(a, b):
    minVal, maxVal = ((a, b), (b, a))[a > b] # :-P

Использование сортировки, встроенные значения min/max или второе решение выше, в этом случае кажется излишним.

И помните, что range(min, max) будет перебирать от min до max - 1!