Dividi l'elenco in elenchi più piccoli (diviso a metà)


150

Sto cercando un modo per dividere facilmente un elenco di pitone a metà.

In modo che se ho un array:

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

Sarei in grado di ottenere:

B = [0,1,2]

C = [3,4,5]

Risposte:


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

Se vuoi una funzione:

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
È necessario forzare la divisione int in Python 3. // è obbligatorio.
Stefan Kendall,

4
Bella soluzione, grazie. Funziona anche con frazioni come 80/20 in Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M

87

Una soluzione un po 'più generica (puoi specificare il numero di parti che desideri, non solo dividere' a metà '):

EDIT : post aggiornato per gestire lunghezze di elenco dispari

EDIT2 : aggiorna nuovamente il post in base ai commenti informativi di Brians

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
Quando la lista non si divide uniformemente (ad es. Split_list ([1,2,3], 2)), ciò restituirà effettivamente liste Want_parts + 1.
Brian,

3
Un modo migliore secondo me sarebbe: length = len (alist); return [alist [i * length // wanted_parts: (i + 1) * length // wanted_parts] per i nell'intervallo (wanted_parts)]. In questo modo ottieni una distribuzione il più uniforme possibile e ottieni sempre esattamente gli oggetti ricercati (anche i pad con [] if wanted_parts> len (A))
Brian

2
ciao .. cosa significa il simbolo "//" ??
frazman,

2
@Fraz È inteso come commento in linea. Ignora "// wanted_parts" e "// wanted_parts" per eseguire lo script.
PunjCoder il

19
//significa divisione intera. Non dovrebbero essere lasciati fuori poiché sono abbastanza essenziali per far funzionare questo.
Alphadelta14

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

n - la lunghezza predefinita delle matrici di risultati


1
Questo funziona alla grande nella mia situazione, tuttavia sta aggiungendo ogni altro ultimo indice di ciascun elenco nel proprio elenco. Difficile da spiegare. Per favore rispondi se puoi aiutare e ti spiegherò di più.
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

Test:

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

risultato:

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

1
utile anche per convertire la lista in matrice
mpgn,

Funziona, ma non del tutto. Sto usando questa funzione in un ciclo e le lunghezze variano. In altre parole: for i,j in zip(list,lengths): print(split(i,j)). Gli elenchi liste lengthshanno la stessa lunghezza. j sta alternando: 5,4,5,4,5 e la funzione split funziona sulle prime due alternanze, ovvero divide la prima ilista per 5 e 4, MA alla successiva iterazione la divide in 4,4, 1. : \ Per favore rispondi se vuoi che ti spieghi di più (pubblica una nuova domanda)
Mike Issa,

15

Se non ti interessa l'ordine ...

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

list[::2]ottiene ogni secondo elemento nell'elenco a partire dal 0 ° elemento.
list[1::2]ottiene ogni secondo elemento nell'elenco a partire dal 1 ° elemento.


4
Attenta denominazione dell'arg listcon l'ombra del list(...)built-in. Ho visto lste list_usato comunemente per evitarlo.
Taylor Edmiston,

3
questo sembra più pitonico (ignorando la denominazione errata)
Tjorriemorrie


11

Ecco una soluzione comune, dividere arr nella parte di conteggio

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

Questo perde l'ordine dell'elenco
Timmah,

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

 return (B,C)

Ho provato e la doppia barra è necessaria per forzare la divisione int in Python 3. Il mio post originale era corretto, anche se wysiwyg si è rotto in Opera, per qualche motivo.


non gestisce len dispari (A) - hai una soluzione per questo?
N997,

6

Esiste una ricevuta Python ufficiale per il caso più generalizzato di suddivisione di un array in array di dimensioni inferiori 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)

Questo frammento di codice proviene dalla pagina doc di Python Itertools .


6

Utilizzo dell'elenco delle sezioni . La sintassi è fondamentalmentemy_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]

Per ottenere la prima metà dell'elenco, taglia dal primo indice a len(i)//2(dove si //trova la divisione intera - quindi 3//2 will give the floored result of1 , instead of the invalid list index of1.5`):

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

..e scambia i valori per ottenere la seconda metà:

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

che dire di elenchi di
lingue

@ N997 Il codice dovrebbe ancora funzionare; hai appena finito con diversi numeri di elementi in ogni elenco. Quindi supponiamo che la lista sia lunga tre voci, l'operatore della divisione 3//2indica il risultato così da 1, quindi ottieni i[:1]quale ti dà [0]e e i[1:]che ti dà[1, 2]
dbr

3

Se hai un grande elenco, è meglio usare itertools e scrivere una funzione per produrre ogni parte secondo necessità:

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)]

Puoi usarlo come:

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

size = len(A) // 2

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

L'output è:

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

Grazie a @thefourtheye e @Bede Constantinides


3

10 anni dopo .. Ho pensato: perché non aggiungerne un altro:

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

2

Mentre le risposte di cui sopra sono più o meno corrette, potresti avere dei problemi se la dimensione dell'array non è divisibile per 2, come risultato di a / 2un essere dispari, è un float in Python 3.0 e nella versione precedente se specifica from __future__ import divisionall'inizio del tuo script. In ogni caso è meglio a // 2scegliere la divisione di interi, ovvero per ottenere una compatibilità "anticipata" del codice.


2

Questo è simile ad altre soluzioni, ma un po 'più veloce.

# 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:]

Uso intelligente dello spostamento binario!
Janusz Skonieczny il

0

Con i suggerimenti di @ChristopheD

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

Un'altra opinione su questo problema nel 2020 ... Ecco una generalizzazione del problema. Interpreto il "dividi un elenco a metà" in modo da essere (cioè solo due elenchi e non ci deve essere lo spillover a un terzo array in caso di uno strano fuori ecc.). Ad esempio, se la lunghezza dell'array è 19 e una divisione per due usando // l'operatore dà 9, e finiremo per avere due array di lunghezza 9 e un array (terzo) di lunghezza 1 (quindi in totale tre array). Se desideriamo una soluzione generale per fornire sempre due array, supporrò che siamo contenti degli array duo risultanti che non sono uguali in lunghezza (uno sarà più lungo dell'altro). E che si presume che vada bene mescolare l'ordine (alternando in questo caso).

"""
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 

Questo concetto funziona per qualsiasi quantità di partizione di elenco come desideri (dovresti modificare il codice a seconda di quante parti dell'elenco desideri). Ed è piuttosto semplice da interpretare. Per velocizzare le cose, puoi persino scrivere questo ciclo in cython / C / C ++ per velocizzare le cose. Poi di nuovo, ho provato questo codice su liste relativamente piccole ~ 10.000 righe e termina in una frazione di secondo.

Solo i miei due centesimi.

Grazie!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.