Tuple yerine liste çıktısıyla zip


94

İki listeden liste listesi yapmanın en hızlı ve en zarif yolu nedir?

Sahibim

In [1]: a=[1,2,3,4,5,6]

In [2]: b=[7,8,9,10,11,12]

In [3]: zip(a,b)
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)]

Ve sahip olmak isterim

In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]

Zip yerine map kullanmayı düşünüyordum, ancak ilk argüman olarak koyacak standart bir kütüphane yöntemi olup olmadığını bilmiyorum.

Bunun için kendi işlevimi tanımlayabilirim ve haritayı kullanabilirim, sorum şu ki zaten bir şey uygulanmış mı? Hayır da bir cevaptır.


1
Peki, gerçekten listelere ihtiyacın var mı? Sonuçlarla ne yapacaksın?
Karl Knechtel

14
Bir örnek sklearn olabilir, burada çoğu kez verilerin bu şekilde organize edilmesi gerekir.
tumultous_rooster

Yanıtlar:


101

2'den fazla listeyi sıkıştırıyorsanız (hatta bu konuda sadece 2 tane), okunabilir bir yol şöyle olacaktır:

[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]

Bu, liste anlayışlarını kullanır ve listedeki (tuples) her bir öğeyi listelere dönüştürür.


54

Cevabı neredeyse kendin aldın. Bunun mapyerine kullanmayın zip. map AND kullanın zip.

Zarif ve işlevsel bir yaklaşım için haritayı zip ile birlikte kullanabilirsiniz:

list(map(list, zip(a, b)))

zipbir demet listesi döndürür. Listedeki her bir demet üzerinde map(list, [...])arama listyapar. list(map([...])harita nesnesini okunabilir bir listeye dönüştürür.


python 3 toplama işlemlerini döndürme talihsiz kararı generator, buradaki iki katının maliyetini empoze eder list.
StephenBoesch

15

Zip işlevinin zarafetini seviyorum, ancak operatör modülünde itemgetter () işlevini kullanmak çok daha hızlı görünüyor. Bunu test etmek için basit bir komut dosyası yazdım:

import time
from operator import itemgetter

list1 = list()
list2 = list()
origlist = list()
for i in range (1,5000000):
        t = (i, 2*i)
        origlist.append(t)

print "Using zip"
starttime = time.time()
list1, list2 = map(list, zip(*origlist))
elapsed = time.time()-starttime
print elapsed

print "Using itemgetter"
starttime = time.time()
list1 = map(itemgetter(0),origlist)
list2 = map(itemgetter(1),origlist)
elapsed = time.time()-starttime
print elapsed

Zip'in daha hızlı olmasını bekliyordum, ancak itemgetter yöntemi uzun bir atışla kazandı:

Using zip
6.1550450325
Using itemgetter
0.768098831177

2
Bu, OP'nin yapmaya çalıştığı şeyin bir aktarımıdır. Gönderinizi bunu yansıtacak şekilde güncelleyebilir misiniz? Yani, OP iki listeyi listeye veya keyfi sayıda çifte dönüştürüyor. Rasgele sayıda çifti bir çift listeye dönüştürüyorsunuz.
Mad Fizikçi

Bu hangi python sürümü ile ölçülür?
Moberg

Hatırlamıyorum, iki yıl önceydi ama büyük olasılıkla 2.6 veya 2.7. Kodu kopyalayıp kendi sürümünüzde / platformunuzda deneyebileceğinizi hayal ediyorum.
kslnet

2
python 2 zipgerçek bir liste oluşturur. Bu işleri yavaşlatır. O zaman zipile değiştirmeyi deneyin itertools.izip.
Jean-François Fabre

Python 3.5'te zip 3.5 saniye sürer ve itemgetter 0.10 saniye sürer. Liste anlayışlarını sevenler için de list1 = [x[0] for x in origlist]işe yarar list1 = map(itemgetter(0), origlist).
Elias Strehle

3

Genelde lambda kullanmayı sevmem ama ...

>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = lambda a, b: [list(c) for c in zip(a, b)]
>>> c(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

Ekstra hıza ihtiyacınız varsa, harita biraz daha hızlıdır:

>>> d = lambda a, b: map(list, zip(a, b))
>>> d(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

Bununla birlikte, haritanın pirtonik olmadığı kabul edilir ve yalnızca performans ayarı için kullanılmalıdır.


4
lambdaBuraya ne ekler? Bir fonksiyon çağırmak yerine sadece ifadeyi yazabilir (gerçekten karmaşık değildir) ve bunun için bir fonksiyon istese bile, acısız bir şekilde iki satırda tanımlanabilir (biri dönüş anahtarınız bozuksa veya deliyse) . mapöte yandan, ilk argüman düz bir işlev olacaksa (a'nın aksine lambda) tamamen iyidir .

1
Bir işlev istedi. Ama katılıyorum - muhtemelen fazladan hattı ödemek daha iyi. Haritaya gelince, liste anlamalarının neredeyse her zaman daha net olduğuna inanıyorum.
Ceasar Bautista

1
Ben öneriyoruz mapüzerinde lambda. yani map(list, zip(a,b)). Listelerin anlaşılması biraz daha net olabilir, ancak harita daha hızlı olmalı (test edilmemiş)
inspectorG4dget

Demek istediğim, yine, OP'nin hıza ihtiyacı varsa, harita gidilecek yol. Ancak genel olarak ve özellikle Python'da hız yerine okunabilirliği vurgulayın (aksi takdirde erken optimizasyona dalarsınız).
Ceasar Bautista

3

Buna ne dersin?

>>> def list_(*args): return list(args)

>>> map(list_, range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Ya da daha iyisi:

>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

Bu bana diğerlerinden daha iyi bir cevap gibi görünüyor, çünkü burada bir zip yapmayarak ve doğrudan bir liste oluşturarak bir adımı azaltıyoruz. Awesome
Akshay Hazari

2

Numpy kullanma

Zarafetin tanımı oldukça tartışmalı olabilir, ancak numpybir dizinin oluşturulması ve listeye dönüştürülmesi (gerekirse ...) üzerinde çalışıyorsanız, mapişlev veya liste anlama ile karşılaştırıldığında çok verimli olmasa da çok pratik olabilir .

import numpy as np 
a = b = range(10)
zipped = zip(a,b)
result = np.array(zipped).tolist()
Out: [[0, 0],
 [1, 1],
 [2, 2],
 [3, 3],
 [4, 4],
 [5, 5],
 [6, 6],
 [7, 7],
 [8, 8],
 [9, 9]]

Aksi takdirde, zipdoğrudan kullanabileceğiniz işlevi atlarsanız np.dstack:

np.dstack((a,b))[0].tolist()

1

Listeyi anlamak çok basit bir çözüm olurdu sanırım.

a=[1,2,3,4,5,6]

b=[7,8,9,10,11,12]

x = [[i, j] for i, j in zip(a,b)]

print(x)

output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.