Вложенный, Если альтернативный Python

#python

Вопрос:

я получил этот код, и мне нужно найти более читаемый и функциональный способ его написания, в этом проекте используется python 3.6

 level_buy = 62 level=0 a1= range(1,10) a2= range(12,16) a3= range(18,29) a4= range(34,46) a5= range(54,63) a6= range(73,85) b1= range(10,12) b2= range(16,18) b3= range(29,34) b4= range(46,54) b5= range(63,73) if recomendation=='buy':  if level_buy in a1:  level=a2[0]  if level_buy in b1:  level=b2[0]  if level_buy in a2:  level=a3[0]  if level_buy in b2:  level=b3[0]  if level_buy in a3:  level=a4[0]  if level_buy in b3:  level=b4[0]  if level_buy in a4:  level=a5[0]  if level_buy in b4:  level=b5[0]  if level_buy in a5:  level=a6[0]  if level_buy in b5:  level=85  if level_buy in a6:  level=85  

Это должно вернуться, если level_buy находится в одном из заданных диапазонов, установите level = первое число в следующем диапазоне. Пример: level_buy=62, если я вызову уровень, должно быть возвращено 73

Заранее спасибо

Комментарии:

1. Как работают эти диапазоны? Почему переход с 1-10 на 12-16, а затем на 18-29?

2. Нет, но python 3.10 добавляет операторы соответствия для структур, подобных регистру.

3. По-моему, это выглядит довольно читабельно. Что с ним не так? Может быть, включите его в функцию, если хотите, чтобы он выглядел красивее.

4. Прежде всего, вы можете сделать эти инструкции elif, чтобы ваша программа работала возможно быстрее

5. @eagle33322 не вижу, как это было бы более читабельно, и я все равно не уверен, что это хороший вариант использования для сопоставления шаблонов.

Ответ №1:

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

 ranges = (a1, b1, a2, b2, a3, b3, a4, b4, a5, b5) if recomendation == 'buy':  for i, ab in enumerate(ranges[:-1]):  if level_buy in ab:  level = ranges[i 1][0]  break  else:  level=85 print(level)  

Комментарии:

1. уровень присваивается первому элементу следующего диапазона, а не диапазону, в котором он был найден.

2. Хорошо подмечено, спасибо. Это должно все исправить.

3. Кроме того, это else должно быть прикреплено к if , или к for ?

4. for , но они функционально эквивалентны. Я все равно это исправил.

Ответ №2:

Вы могли бы сохранить диапазоны в списке вместо множества отдельных переменных:

 ranges = [  range(1,10),  range(12,16),  range(18,29),  ... ]  

А затем вы можете повторить список:

 for pos, r in enumerate(ranges):  if level_buy in r:  level = ranges[pos 1][0]  

Если вы не хотите, чтобы последний a диапазон соединялся с первым b диапазоном, вы, возможно, могли бы сохранить два списка.

Ответ №3:

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

 level_buy = 62  thresholds = [1,10,12,16,18,29,34,46,54,63,73,85] selection = [t for t in thresholds if level_buy lt; t] level = selection[1] if len(selection) gt; 1 else 85  

Ответ №4:

Ты пропустил объявление recommendation . Но вот альтернатива вашему сценарию, если вы хотите сохранить логику, аналогичную той, которую вы опубликовали:

 from itertools import chain  recommendation = "buy" level_buy = 62 level = 0 a1 = range(1, 10) a2 = range(12, 16) a3 = range(18, 29) a4 = range(34, 46) a5 = range(54, 63) a6 = range(73, 85) b1 = range(10, 12) b2 = range(16, 18) b3 = range(29, 34) b4 = range(46, 54) b5 = range(63, 73)  a_ranges = [a1, a2, a3, a4, a5, a6] b_ranges = [b1, b2, b3, b4, b5] combined_ranges = chain.from_iterable(zip(a_ranges, b_ranges))  if recommendation == "buy":  for range_ in combined_ranges:  if level_buy in range_:  level = range_[0]  break  print(level)  

Ответ №5:

Если вы звоните по этому номеру много раз, и у вас не слишком много диапазонов для установки, и вы хотите, чтобы для таблицы поиска требовалась предварительная стоимость и память, вы можете предварительно обработать это:

 from itertools import chain level_sets = [(range(1,10), 12),  (range(12,16), 18),  (range(18,29), 34),  (range(34,46), 54),  (range(54,63), 73),  (range(73,85), 85),  (range(10,12), 16),  (range(16,18), 29),  (range(29,34), 46),  (range(46,54), 63),  (range(63,73), 85)]  levels = {l: s for l, s in chain(*([(k, v) for k in r] for r, v in level_sets))}  ...  for buy in recommendation_list:   level = levels.get(level_buy)  

Это в основном говорит о том, что для каждого целого числа у вас есть какой-то уровень, на который он будет указывать. Преимущество этого способа заключается в том, что каждый раз, когда вам нужно получить уровень для покупки уровня, это операция O(1) — поэтому, если у вас было большое количество рекомендаций, которые нужно сделать, это будет иметь небольшую первоначальную стоимость (построение таблицы поиска), а затем очень небольшую добавочную стоимость (поиск покупки уровня). Это контрастирует с отсутствием первоначальных затрат и стоимостью O(n) каждый раз, когда n у вас есть количество диапазонов.