Dividir a lista em listas menores (dividir ao meio)


150

Estou procurando uma maneira de dividir facilmente uma lista python ao meio.

Então, se eu tiver uma matriz:

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

Eu seria capaz de obter:

B = [0,1,2]

C = [3,4,5]

Respostas:


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

Se você deseja uma função:

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
Você precisa forçar a divisão int no Python 3. // é necessário.
23909 Stefan Kendall

4
Boa solução, obrigado. Ele também funciona com frações como 80/20 em Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M

87

Uma solução um pouco mais genérica (você pode especificar o número de partes que deseja, e não apenas dividir 'ao meio'):

EDIT : postagem atualizada para lidar com comprimentos de lista ímpares

EDIT2 : atualização post novamente com base em comentários informativos de 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 a lista não se divide uniformemente (por exemplo, lista_dividida ([1,2,3], 2))), na verdade, ele retornará listas de peças_queridas + 1.
Brian

3
Uma maneira melhor que eu acho que seria: length = len (alist); retorne [alist [i * comprimento // partes_de_quadro: (i + 1) * comprimento // partes_de_quadro] para i no intervalo (partes_quadro)]. Dessa forma, você obter uma ainda possível distribuição, e sempre obter wanted_parts exatamente itens (até mesmo almofadas com [] se wanted_parts> len (A))
Brian

2
oi .. o que significa o símbolo "//"?
frazman

2
@Fraz É um comentário embutido. Ignore "// Want_parts" e "// Want_parts" para executar o script.
precisa saber é o seguinte

19
//significa divisão inteira. Eles não devem ser deixados de fora, pois são bastante essenciais para fazer esse trabalho.
Alphadelta14

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

n - o comprimento predefinido das matrizes de resultados


1
Isso funciona muito bem na minha situação, mas anexa todos os outros índices de cada lista em sua própria lista. Difícil de explicar. Por favor, responda se você puder ajudar e eu explicarei mais.
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

Teste:

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

resultado:

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

1
também é útil para converter lista em matriz
mpgn

Isso funciona, mas não completamente. Estou usando esta função em um loop, e os comprimentos variam. Em outras palavras: for i,j in zip(list,lengths): print(split(i,j)). As listas liste lengthstêm o mesmo comprimento. j é alternado: 5,4,5,4,5, e a função de divisão funciona nas duas primeiras alternações, ou seja, divide o primeiro ida lista por 5 e 4, mas, na próxima iteração, o divide em 4,4, 1 : \ Por favor, responda se você gostaria de me explicar mais (postar uma nova pergunta)
Mike Issa

15

Se você não se importa com o pedido ...

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

list[::2]obtém cada segundo elemento da lista começando no 0º elemento.
list[1::2]obtém cada segundo elemento da lista começando no 1º elemento.


4
Nomear cuidadosamente o argumento listcom sombreamento do interno list(...). Eu já vi lste list_usei comumente para evitá-lo.
Taylor Edmiston

3
este se sente mais pythônico (ignorando a nomenclatura incorreta)
Tjorriemorrie


11

Aqui está uma solução comum, dividir arr em parte de contagem

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

Isso perde a ordem da lista
Timmah 20/09/18

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

 return (B,C)

Eu testei e a barra dupla é necessária para forçar a divisão int no python 3. Minha postagem original estava correta, embora o wysiwyg tenha quebrado no Opera, por algum motivo.


ele não lida com len (A) - você tem solução para isso?
N997

6

Existe uma receita oficial do Python para o caso mais generalizado de dividir uma matriz em matrizes menores de tamanho 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)

Este trecho de código é da página de documentos python itertools .


6

Usando o fatiamento de lista . A sintaxe é basicamentemy_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]

Para obter a primeira metade da lista, você fatia do primeiro índice para len(i)//2(onde //está a divisão inteira - então 3//2 will give the floored result of1 , instead of the invalid list index of1,5`):

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

..e troque os valores para obter a segunda metade:

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

what about odd len lists)
N997 1/19/19

@ N997 O código ainda deve funcionar; você acaba com diferentes números de itens em cada lista. Então diga a lista é três itens longa, os pisos operador de divisão o resultado até 3//21, então você obtém i[:1]o que lhe dá [0]e e i[1:]que dá[1, 2]
DBR

3

Se você tem uma lista grande, é melhor usar as ferramentas de controle e escrever uma função para produzir cada parte conforme necessário:

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

Você pode usar isso como:

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

size = len(A) // 2

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

A saída é:

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

Obrigado a @thefourtheye e @Bede Constantinides


3

10 anos depois .. eu pensei - por que não adicionar outro:

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

2

Embora as respostas acima sejam mais ou menos corretas, você pode ter problemas se o tamanho da sua matriz não for divisível por 2, como resultado de a / 2um fato estranho ser um flutuador no python 3.0 e na versão anterior se você especifique from __future__ import divisionno início do seu script. De qualquer forma, é melhor você optar pela divisão de números inteiros, ou seja a // 2, para obter compatibilidade "avançada" do seu código.


2

Isso é semelhante a outras soluções, mas um pouco mais rápido.

# 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 inteligente de deslocamento binário!
Janusz Skonieczny 16/07

0

Com dicas de @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

Outra visão sobre esse problema em 2020 ... Aqui está uma generalização do problema. Eu interpreto o 'dividir uma lista ao meio' como sendo .. (ou seja, apenas duas listas e não haverá transbordamento para uma terceira matriz no caso de uma saída ímpar etc). Por exemplo, se o comprimento da matriz for 19 e uma divisão por duas usando //, o operador fornecerá 9, e teremos duas matrizes de comprimento 9 e uma matriz (terceira) de comprimento 1 (totalizando três matrizes). Se quisermos que uma solução geral forneça duas matrizes o tempo todo, assumirei que estamos felizes com as matrizes resultantes que não são iguais em comprimento (uma será maior que a outra). E que é considerado aceitável que a ordem seja misturada (alternando neste 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 

Esse conceito funciona para qualquer quantidade de partição de lista que você desejar (você precisará ajustar o código dependendo de quantas partes da lista desejar). E é bastante simples de interpretar. Para acelerar as coisas, você pode até escrever esse loop em cython / C / C ++ para acelerar as coisas. Então, novamente, eu tentei esse código em listas relativamente pequenas ~ 10.000 linhas e termina em uma fração de segundo.

Apenas meus dois centavos.

Obrigado!

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.