Есть ли в Python удобный однострочный список для генерации списка чисел и их отрицательных аналогов?
Например, скажем, я хочу создать список с номерами от 6 до 9 и от -6 до -9.
Мой текущий подход:
l = [x for x in range(6,10)]
l += [-x for x in l]
Простой «однострочник» будет:
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
Однако создание двух списков и последующее их объединение кажется неудобным.
python
python-3.x
ВНО
источник
источник
scalar or array-like, shape
будет в порядке.Ответы:
Я не уверен, имеет ли значение порядок, но вы могли бы создать кортеж и распаковать его в понимании списка.
источник
Создайте красивую и читаемую функцию:
Применение:
Так вы получаете удобную однострочку для чего угодно. Старайтесь не выглядеть как волшебный профессиональный хакер.
источник
y
вsignedValue
. Для меня реальная добавленная ценность подхода «определить функцию» состояла бы в том, чтобы доставлять результаты в строгом порядке, который задавался вопрос (положительный, затем отрицательный), избегая при этом проблемы однострочника Бармара,chain
в котором немного отличающиеся числовые аргументы имеют быть жестко запрограммированным в два раза.list
какому-либо другому.) После многих лет попыток систематизировать, как лучше принимать эти решения, единственный общий принцип, который имеет смысл для меня : если есть очевидное, доброе имя, которое можно дать в программе, воспользуйтесь возможностью (и функции - один из способов сделать это).Я бы сказал, что самое простое решение - распаковать два диапазона в список с помощью
*
оператора распаковки:Это не только самый короткий предложенный ответ, но и самый эффективный, потому что он создает только один список и не включает никаких вызовов функций, кроме двух
range
.Я проверил это, протестировав ответы на все вопросы с помощью
timeit
модуля:(тестирование timeit, выполненное с Python 3.6.9 на моем собственном компьютере (средние характеристики))
источник
[*range(x, y), *range(-y + 1, -x + 1)]
Вы можете использовать
itertools.chain()
для объединения двух диапазонов.источник
Вы можете использовать
itertools.product
, который является декартовым произведением.Это может быть медленнее, потому что вы используете умножение, но должно быть легко читаемым.
Если вы хотите чисто функциональное решение, вы также можете импортировать
itertools.starmap
иoperator.mul
:Однако это менее читабельно.
источник
product
,starmap
иopertaor.mul
излишне тупым по сравнению с вложенным списковыми, но я одобряю предложение использовать умножение.[x * sign for sign in (1, -1) for x in range(6, 10)]
только на 10% медленнее, чем[y for x in range(6, 10) for y in (x, -x)]
, а в тех случаях, когда порядок важен, более чем в 3 раза быстрее, чем сортировка по кортежу.starmap
и егоmul
следует избегать, но я думаю,product
что он делает его более читабельным, поскольку он группирует итераторы и их элементы по отдельности. Двойные циклы в понимании списка также могут сбивать с толку из-за их неожиданного порядка.Вы действительно близки, комбинируя два
range
объекта. Но есть более простой способ сделать это:То есть преобразовать каждый
range
объект в список, а затем объединить два списка.Другой подход, использующий itertools:
itertools.chain()
похоже на обобщенный+
: вместо добавления двух списков он создает один итератор за другим, чтобы создать «супер-итератор». Затем передайте это,list()
и вы получите конкретный список со всеми нужными числами в памяти.источник
[x for x in ...]
которое лучше написаноlist(...)
.Взвешивание с еще одной возможностью.
Если вы хотите удобочитаемости, ваш оригинальный однострочный текст был довольно хорошим, но я бы изменил диапазоны на те же, что и на мой взгляд, отрицательные границы делают вещи менее ясными.
источник
ИМО подход, использующий
itertools.chain
представленный в нескольких других ответах, является определенно самым чистым из предоставленных до сих пор.Тем не менее, поскольку в вашем случае порядок значений не имеет значения , вы можете избежать необходимости определять два явных
range
объекта и, таким образом, избегать выполнения математических операций, необходимых для отрицательнойrange
индексации, используяitertools.chain.from_iterable
:Немного многословно, но достаточно читабельно.
Другой подобный вариант - использовать распаковку кортежей / аргументов с помощью plain
chain
:Более кратко, но я обнаружил, что распаковка кортежа сложнее в быстром сканировании.
источник
Это вариация на тему (см @Derte Trdelnik «s ответ ) , следуя философии ,
itertools
гдеИдея состоит в том, что, хотя мы определяем новую функцию, мы могли бы также сделать ее общей:
и применить его к конкретному
range
итератору:источник
Если вы хотите сохранить указанный вами порядок, вы можете использовать встроенный в Python генератор диапазонов с условным условием:
Что дает вам вывод:
А также работает с 0 в качестве начала для полного диапазона.
источник
start
.Там могут быть разные способы сделать работу.
Заданные переменные: 1. start = 6 2. stop = 10
Вы можете попробовать это также для другого подхода:
источник
Я просто люблю симметрии.
а = 6 б = 10
nums = [x + y для x in (- (a + b-1), 0) для y в диапазоне (a, b)]
Результат должен быть -9, -8, ..., 8, 9.
Я считаю, что выражение чисел может быть улучшено, то, что следует за "в" и "диапазоне", все еще выглядит мне неуравновешенным.
источник