Listeyi daha küçük listelere ayır (ikiye bölün)


150

Bir python listesini kolayca ikiye bölmenin bir yolunu arıyorum.

Böylece bir dizi varsa:

A = [0,1,2,3,4,5]

Ben alabilirim:

B = [0,1,2]

C = [3,4,5]

Yanıtlar:


226
A = [1,2,3,4,5,6]
B = A[:len(A)//2]
C = A[len(A)//2:]

Bir işlev istiyorsanız:

def split_list(a_list):
    half = len(a_list)//2
    return a_list[:half], a_list[half:]

A = [1,2,3,4,5,6]
B, C = split_list(A)

70
Python 3'te int bölünmesini zorlamanız gerekir. // gereklidir.
Stefan Kendall

4
Güzel çözüm, teşekkürler. Ayrıca Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M

87

Biraz daha genel bir çözüm (sadece 'ikiye' bölmekle kalmayıp istediğiniz parça sayısını belirtebilirsiniz):

EDIT : tek liste uzunluklarını işlemek için güncellenmiş yazı

EDIT2 : Brians bilgilendirici yorumlarına dayanarak yayını tekrar güncelleyin

def split_list(alist, wanted_parts=1):
    length = len(alist)
    return [ alist[i*length // wanted_parts: (i+1)*length // wanted_parts] 
             for i in range(wanted_parts) ]

A = [0,1,2,3,4,5,6,7,8,9]

print split_list(A, wanted_parts=1)
print split_list(A, wanted_parts=2)
print split_list(A, wanted_parts=8)

2
Liste eşit olarak bölünmediğinde (ör. Split_list ([1,2,3], 2)) bu gerçekten aranan_parts + 1 listelerini döndürür.
Brian

3
Bence daha iyi bir yol: length = len (alist); aralıktaki (aranan_parts) i için [alist [i * uzunluk // aranan_parts: (i + 1) * uzunluk // aranan_parts]]. Bu şekilde mümkün olduğunca eşit bir dağılım elde edersiniz ve her zaman tam olarak aranan_parts öğelerini alırsınız (aranan_parts> len (A) ise [] ile bile pedler)
Brian

2
merhaba .. "//" sembolü ne anlama geliyor ??
frazman

2
@Fraz Bu satır içi yorum anlamına gelir. Komut dosyasının yürütülmesini sağlamak için "// wanted_parts" ve "// wanted_parts" öğelerini yok sayın.
PunjCoder

19
//tamsayı bölümü anlamına gelir. Bu işi yapmak için oldukça gerekli oldukları için dışarıda bırakılmamalıdırlar.
Alphadelta14

43
f = lambda A, n=3: [A[i:i+n] for i in range(0, len(A), n)]
f(A)

n - sonuç dizilerinin önceden tanımlanmış uzunluğu


1
Bu benim durumumda harika çalışıyor, ancak her listenin diğer son dizinlerini kendi listesine ekliyor. Açıklaması zor. Lütfen yardımcı olabilirseniz cevap verin ve daha fazla açıklayacağım.
Mike Issa

34
def split(arr, size):
     arrs = []
     while len(arr) > size:
         pice = arr[:size]
         arrs.append(pice)
         arr   = arr[size:]
     arrs.append(arr)
     return arrs

Ölçek:

x=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
print(split(x, 5))

sonuç:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]

1
listeyi matrise dönüştürmek için de yararlı
mpgn

Bu işe yarıyor, ama tam olarak değil. Bu işlevi bir döngüde kullanıyorum ve uzunlukları değişiyor. Başka bir deyişle: for i,j in zip(list,lengths): print(split(i,j)). listVe lengthslisteleri aynı uzunluktadır. j dönüşümlüdür: 5,4,5,4,5 ve bölme işlevi ilk iki alternatifte çalışır, yani ilistenin ilkini 5 ve 4'e böler, ancak bir sonraki yinelemede 4,4'te böler, 1. : \ Lütfen daha fazla açıklamamı isterseniz yanıtlayın (yeni bir soru gönderin)
Mike Issa

15

Siparişi önemsemiyorsanız ...

def split(list):  
    return list[::2], list[1::2]

list[::2]0 öğesinden başlayarak listedeki her ikinci öğeyi alır.
list[1::2]listedeki her ikinci öğeyi 1. öğeden başlayarak alır.


4
Dahili listgölgeleme ile arg ismini dikkatli bir şekilde adlandırın list(...). Bunu önlemek için yaygın olarak gördüm lstve list_kullandım.
Taylor Edmiston

3
bu en pythonic hissediyor (yanlış
isimlemeyi


11

İşte ortak bir çözüm, arr sayım bölümüne bölünmüş

def split(arr, count):
     return [arr[i::count] for i in range(count)]

Bu listenin sırasını kaybeder
Timmah

9
def splitter(A):
    B = A[0:len(A)//2]
    C = A[len(A)//2:]

 return (B,C)

Test ettim ve çift eğik çizgi python 3'te int bölünmesini zorlamak için gereklidir. Wysiwyg bir sebepten ötürü Opera'da kırılmış olmasına rağmen orijinal yazım doğruydu.


tuhaf len (A) ile uğraşmaz - bunun için bir çözümünüz var mı?
N997

6

Bir diziyi daha küçük boyutlu dizilere bölmek için daha genelleştirilmiş bir durum için resmi bir Python makbuzu vardır n.

from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "Collect data into fixed-length chunks or blocks"
    # grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

Bu kod pasajı python itertools doc sayfasından alınmıştır .


6

Liste dilimleme kullanma . Sözdizimi temel olarakmy_list[start_index:end_index]

>>> i = [0,1,2,3,4,5]
>>> i[:3] # same as i[0:3] - grabs from first to third index (0->2)
[0, 1, 2]
>>> i[3:] # same as i[3:len(i)] - grabs from fourth index to end
[3, 4, 5]

Listenin ilk yarısını almak için, ilk dizinden dilime dilimlersiniz len(i)//2( //tamsayı bölümü - yani 3//2 will give the floored result of1 , instead of the invalid list index of1.5`):

>>> i[:len(i)//2]
[0, 1, 2]

..ve ikinci yarıyı almak için değerleri değiştirin:

>>> i[len(i)//2:]
[3, 4, 5]

garip len listeleri hakkında ne dersiniz)
N997

@ N997 Kod yine de çalışmalıdır; sadece her bir listede farklı sayıda öğe bulunur. Listenin üç öğe uzunluğunda olduğunu söyleyin, bölüm operatörü sonucu 3//2verir 1, o zaman size i[:1]verir [0]ve i[1:]verir[1, 2]
dbr

3

Büyük bir listeniz varsa, itertools'u kullanmak ve her parçayı gerektiği gibi vermek için bir işlev yazmak daha iyidir :

from itertools import islice

def make_chunks(data, SIZE):
    it = iter(data)
    # use `xragne` if you are in python 2.7:
    for i in range(0, len(data), SIZE):
        yield [k for k in islice(it, SIZE)]

Bunu aşağıdaki gibi kullanabilirsiniz:

A = [0, 1, 2, 3, 4, 5, 6]

size = len(A) // 2

for sample in make_chunks(A, size):
    print(sample)

Çıktı:

[0, 1, 2]
[3, 4, 5]
[6]

Teşekkür etmek @thefourtheye ve @Bede Konstantinides


3

10 yıl sonra .. Düşündüm - neden başka bir tane eklemeyelim:

arr = 'Some random string' * 10; n = 4
print([arr[e:e+n] for e in range(0,len(arr),n)])

2

Yukarıdaki cevaplar aşağı yukarı doğru olsa da, dizinizin boyutu 2'ye bölünemezse a / 2, garip bir durumun python 3.0'da bir şamandıra olması durumunda sorun yaşayabilirsiniz. from __future__ import divisionkomut dosyanızın başında belirtin . Her halükarda, tamsayı bölmeye gitmek, yani a // 2kodunuzun "ileri" uyumluluğunu elde etmek için daha iyi olursunuz.


2

Bu diğer çözümlere benzer, ancak biraz daha hızlı.

# Usage: split_half([1,2,3,4,5]) Result: ([1, 2], [3, 4, 5])

def split_half(a):
    half = len(a) >> 1
    return a[:half], a[half:]

İkili vites değiştirmenin akıllıca kullanımı!
Janusz Skonieczny

0

@ChristopheD tarafından ipuçları

def line_split(N, K=1):
    length = len(N)
    return [N[i*length/K:(i+1)*length/K] for i in range(K)]

A = [0,1,2,3,4,5,6,7,8,9]
print line_split(A,1)
print line_split(A,2)

0
#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       

0

2020'de bu sorunu bir kez daha ele alalım ... İşte sorunun genelleştirilmesi. 'Bir listeyi ikiye böl' olarak yorumluyorum. Örneğin, dizi uzunluğu 19 ise ve // ​​işleci kullanan ikiye bölünme 9 değerini verirse, 9 uzunluklu iki diziye ve 1 uzunluklu bir diziye (üçüncü) sahip olacağız (yani toplam üç dizide). Her zaman iki dizi vermek için genel bir çözüm istiyorsak, uzunluk olarak eşit olmayan (biri diğerinden daha uzun olacak) sonuçlanan ikili dizilerden memnun olduğumuzu varsayacağım. Ve siparişin karışık olması için iyi olduğu varsayılır (bu durumda dönüşümlü olarak).

"""
arrayinput --> is an array of length N that you wish to split 2 times
"""
ctr = 1 # lets initialize a counter

holder_1 = []
holder_2 = []

for i in range(len(arrayinput)): 

    if ctr == 1 :
        holder_1.append(arrayinput[i])
    elif ctr == 2: 
        holder_2.append(arrayinput[i])

    ctr += 1 

    if ctr > 2 : # if it exceeds 2 then we reset 
        ctr = 1 

Bu kavram, istediğiniz kadar liste bölümü için çalışır (istediğiniz liste bölümüne bağlı olarak kodu değiştirmeniz gerekir). Ve yorumlanması oldukça kolaydır. İşleri hızlandırmak için, bu döngüyü cython / C / C ++ 'da yazarak işleri hızlandırabilirsiniz. Sonra tekrar, bu kodu nispeten küçük listelerde denedim ~ 10.000 satır ve ikinci bir kısmını bitirir.

Sadece iki sentim.

Teşekkürler!

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.