2016-06-26 3 views
4

Предположим, вы хотите перебрать все целые числа между двумя границами и b (включительно), но не знаете заранее, как a сравнивается с b. Ожидаемое поведение:Цитирование через интервал в любом направлении

def run(a, b): 
    if a < b: 
     for i in range(a, b + 1): 
      print i, 
    elif a > b: 
     for i in range(a, b - 1, -1): 
      print i, 
    else: 
     print a 
    print 

run(3, 6) 
run(6, 3) 
run(5, 5) 

Результат:

3 4 5 6 
6 5 4 3 
5 

Есть ли более элегантное решение? Ниже более кратким, но терпит неудачу, когда a == b:

def run(a, b): 
    for i in range(a, b + cmp(b, a), cmp(b, a)): 
     print i, 
    print 

run(3, 6) 
run(6, 3) 
run(5, 5) 

Результат:

3 4 5 6 
6 5 4 3 
(...) 
ValueError: range() step argument must not be zero 
+1

'для i в диапазоне (min ((a, b)), max ((a, b)) + 1)' было бы самым очевидным способом – TemporalWolf

+0

@TemporalWolf Это дает '3 4 5 6' дважды. – Aristide

+0

Да, я сделал предположение о том, что вы хотели, чтобы они восходили. – TemporalWolf

ответ

7

Это будет работать для всех случаев:

def run(a, b): 
    """Iterate from a to b (inclusive).""" 
    step = -1 if b < a else 1 
    for x in xrange(a, b + step, step): 
     yield x 

понимание, что привело меня к эта формулировка заключалась в том, что step и настройка b были одинаковыми у бота ч ваших дел; после того, как у вас есть инклюзивный конец, вам не нужен специальный случай a == b. Обратите внимание, что я написал его в качестве генератора, так что это не просто print результатов, что делает его более использовать, когда вам нужно интегрировать его с другим кодом:

>>> list(run(3, 6)) 
[3, 4, 5, 6] 
>>> list(run(6, 3)) 
[6, 5, 4, 3] 
>>> list(run(5, 5)) 
[5] 

Использования делегирования генератора в Python 3.3+ (см PEP-380), это становится еще аккуратнее:

def run(a, b): 
    """Iterate from a to b (inclusive).""" 
    step = -1 if b < a else 1 
    yield from range(a, b + step, step) 
+0

Да. Или, в конце концов: 'range (a, b + 2 * int (a Aristide

+2

@Aristide '2 * int (a jonrsharpe

+0

Ха-ха, как насчет '(a TemporalWolf

-3
range(min((a,b)), max((a,b))+1) 
+2

Это происходит в неправильном направлении, когда 'b jonrsharpe

2

Вы почти получили сами:

def run(a, b): 
    for i in range(a, b + (cmp(b, a) or 1), cmp(b, a) or 1): 
     print i, 
    print 

работает просто отлично ... когда cmp(b, a) оценивает до 0 (когда они равны), по умолчанию он равен 1, хотя я определенно считаю, что ответ Джона более изящный, вы были на правильном пути! Я широко использую логику or python при выполнении таких сравнений:

(func() or default) очень полезен для любой функции, которая возвращает нуль, который вы хотите перезаписать. Python оценивает его как False or True и возвращает default.