Apakah ada satu-liner yang nyaman untuk menghasilkan daftar angka dan rekan negatifnya di Python?
Misalnya, saya ingin membuat daftar dengan angka 6 hingga 9 dan -6 hingga -9.
Pendekatan saya saat ini adalah:
l = [x for x in range(6,10)]
l += [-x for x in l]
"Satu garis" sederhana adalah:
l = [x for x in range(6,10)] + [y for y in range(-9, -5)]
Namun, menghasilkan dua daftar dan kemudian bergabung bersama tampaknya tidak nyaman.
python
python-3.x
upe
sumber
sumber
scalar or array-like, shape
akan baik-baik saja.Jawaban:
Saya tidak yakin jika pesanan itu penting, tetapi Anda bisa membuat tuple dan membukanya dalam pemahaman daftar.
sumber
Buat fungsi yang bagus dan mudah dibaca:
Pemakaian:
Itulah cara Anda mendapatkan satu-liner yang nyaman untuk apa pun. Hindari berusaha terlihat seperti hacker pro sihir.
sumber
y
menjadisignedValue
. Bagi saya nilai tambah nyata dari pendekatan define-a-function adalah untuk memberikan hasil dalam urutan ketat pertanyaan yang diajukan (positif, kemudian negatif) sambil menghindari masalahchain
one-liner Barmar di mana argumen numerik yang sedikit berbeda memiliki menjadi hard-kode dua kali.list
atau apa pun.) Setelah bertahun-tahun mencoba mengodifikasi cara terbaik untuk membuat keputusan ini, satu-satunya prinsip umum yang masuk akal bagi saya : jika ada nama yang jelas dan bagus untuk diberikan kepada sesuatu dalam program, ambil kesempatan untuk melakukannya (dan fungsi adalah salah satu cara kami melakukan ini).Saya akan mengatakan solusi paling sederhana adalah membongkar dua rentang ke dalam daftar menggunakan
*
operator membongkar:Tidak hanya ini jawaban terpendek yang diajukan, tetapi juga yang paling berkinerja, karena hanya membangun satu daftar dan tidak melibatkan pemanggilan fungsi selain keduanya.
range
.Saya memverifikasi ini dengan menguji semua jawaban pertanyaan ini menggunakan
timeit
modul:(pengujian timeit dilakukan dengan Python 3.6.9 di komputer saya sendiri (spesifikasi rata-rata))
sumber
[*range(x, y), *range(-y + 1, -x + 1)]
Anda dapat menggunakan
itertools.chain()
untuk menggabungkan dua rentang.sumber
Anda dapat menggunakan
itertools.product
, yang merupakan produk kartesius.Ini mungkin lebih lambat karena Anda menggunakan perkalian, tetapi harus mudah dibaca.
Jika Anda menginginkan solusi yang berfungsi murni, Anda juga dapat mengimpor
itertools.starmap
danoperator.mul
:Namun, ini kurang dapat dibaca.
sumber
product
,starmap
danopertaor.mul
tidak perlu tumpul dibandingkan dengan daftar bersarang comprehensions, tapi saya menyetujui saran menggunakan perkalian.[x * sign for sign in (1, -1) for x in range(6, 10)]
hanya 10% lebih lambat dari pada[y for x in range(6, 10) for y in (x, -x)]
, dan dalam kasus di mana urutan penting, lebih dari 3x lebih cepat daripada menyortir pendekatan berbasis tuple.starmap
danmul
harus dihindari, tapi saya pikirproduct
membuatnya lebih mudah dibaca, karena mengelompokkan iterator dan elemen mereka secara terpisah. Loop ganda dalam pemahaman daftar juga dapat membingungkan, karena urutannya yang tidak terduga.Anda benar-benar dekat, dengan menggabungkan dua
range
objek. Tetapi ada cara yang lebih mudah untuk melakukannya:Artinya, konversikan setiap
range
objek ke daftar, dan kemudian gabungkan dua daftar.Pendekatan lain, menggunakan itertools:
itertools.chain()
seperti generalisasi+
: alih-alih menambahkan dua daftar, ia mengaitkan satu iterator demi satu untuk membuat "super-iterator". Kemudian berikan itu kelist()
dan Anda mendapatkan daftar konkret, dengan semua angka yang Anda inginkan dalam memori.sumber
[x for x in ...]
dieja lebih baiklist(...)
.Menimbang dengan kemungkinan lain.
Jika Anda ingin keterbacaan satu-liner asli Anda cukup bagus, tapi saya akan mengubah rentang menjadi sama karena saya pikir batas negatif membuat segalanya menjadi kurang jelas.
sumber
IMO pendekatan menggunakan
itertools.chain
disajikan dalam beberapa jawaban lain jelas merupakan yang terbersih dari yang disediakan sejauh ini.Namun, karena dalam kasus Anda urutan nilai tidak masalah , Anda dapat menghindari keharusan mendefinisikan dua
range
objek eksplisit , dan dengan demikian menghindari melakukan semua off-by-one matematika yang diperlukan untukrange
pengindeksan negatif , dengan menggunakanitertools.chain.from_iterable
:Tad verbose, tetapi cukup mudah dibaca.
Pilihan lain yang serupa adalah menggunakan tuple / argumen membongkar dengan polos
chain
:Lebih ringkas, tetapi saya menemukan tuple membongkar lebih sulit untuk grok dalam pemindaian cepat.
sumber
Ini adalah variasi pada tema (lihat @Derte Trdelnik 's jawaban ) mengikuti filosofi
itertools
di manaIdenya adalah bahwa, sementara kita mendefinisikan fungsi baru, kita mungkin membuatnya secara umum:
dan menerapkannya pada
range
iterator tertentu :sumber
Jika Anda ingin menjaga urutan yang Anda tentukan, Anda dapat menggunakan generator rentang built-in Python dengan syarat:
Yang memberi Anda output:
Dan juga bekerja dengan 0 sebagai awal untuk rentang penuh.
sumber
start
.Mungkin ada berbagai cara untuk menyelesaikan pekerjaan.
Variabel yang diberikan: 1. mulai = 6 2. berhenti = 10
Anda dapat mencoba ini juga, untuk pendekatan yang berbeda:
sumber
Aku suka simetri.
a = 6 b = 10
nums = [x + y untuk x in (- (a + b-1), 0) untuk y dalam rentang (a, b)]
Hasilnya harus -9, -8, ..., 8, 9.
Saya percaya bahwa ekspresi nums dapat ditingkatkan, yang mengikuti "dalam" dan "kisaran" masih terlihat tidak seimbang bagi saya.
sumber