Разделить список на более мелкие списки (разделить пополам)

Я ищу способ легко разделить список Python пополам.

Итак, если у меня есть массив:

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

Я смогу получить:

B = [0,1,2]

C = [3,4,5]

person corymathews    schedule 15.04.2009    source источник


Ответы (17)


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

Если вам нужна функция:

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)
person Jason Coon    schedule 15.04.2009
comment
Вам нужно принудительно использовать деление int в Python 3. // Требуется. - person Stefan Kendall; 15.04.2009
comment
Хорошее решение, спасибо. Он также работает с дробями типа 80/20 в Python3 B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:] - person Gergely M; 04.03.2019

Немного более общее решение (вы можете указать необходимое количество частей, а не просто разделить их пополам):

РЕДАКТИРОВАТЬ: обновленное сообщение для обработки нечетных длин списков

EDIT2: обновите сообщение еще раз на основе информативных комментариев Брайанса.

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)
person ChristopheD    schedule 15.04.2009
comment
Когда список не делится равномерно (например, split_list ([1,2,3], 2)), это фактически вернет списки wish_parts + 1. - person Brian; 15.04.2009
comment
Это правильно, я сомневался, что должно быть правильным подходом (иметь еще одну часть или иметь еще один элемент в последнем списке). Я обновлю свой пост, спасибо за комментарий. - person ChristopheD; 16.04.2009
comment
На самом деле, это все равно не сработает: у вас может быть остаток ›1. split_list (range (5), 3) даст 5 списков с приведенным выше кодом. Работать с этими случаями также сложнее, так как вам нужно равномерно распределить список (например, для списка из 19 элементов, состоящего из 10 частей, вам не нужно 9 * 1 элемент и один с 9.) - person Brian; 16.04.2009
comment
Я думаю, что лучше было бы: length = len (alist); return [alist [i * длина // желаемые_ части: (i + 1) * длина // требуемые_ части] для i в диапазоне (желаемые_ части)]. Таким образом, вы получите максимально возможное распределение и всегда будете получать именно те элементы, которые требуется (даже отметки с [], если хотят_запчасти ›len (A)) - person Brian; 16.04.2009
comment
Очень хорошее решение, спасибо большое. Гораздо короче, чем я думал ... я обновлю свой пост. - person ChristopheD; 17.04.2009
comment
привет .. что означает символ // ?? - person frazman; 21.06.2012
comment
@Fraz Это означает встроенный комментарий. Игнорировать // желаемые_ части и // желаемые_ части для выполнения скрипта. - person PunjCoder; 02.08.2012
comment
// означает целочисленное деление. Их не следует упускать из виду, поскольку они очень важны для выполнения этой работы. - person Alphadelta14; 20.11.2013

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

n - предопределенная длина массивов результатов

person Jaro    schedule 07.02.2010
comment
Это отлично работает в моей ситуации, однако добавляет каждый последний индекс каждого списка в свой собственный список. Тяжело объяснить. Пожалуйста, ответьте, если вы можете помочь, и я объясню вам больше. - person Mike Issa; 05.02.2016

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

Тестовое задание:

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

результат:

[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]
person Siamand    schedule 18.04.2014
comment
также полезно преобразовать список в матрицу - person mpgn; 11.11.2015
comment
Это работает, но не совсем. Я использую эту функцию в цикле, и длина может быть разной. Другими словами: for i,j in zip(list,lengths): print(split(i,j)). Списки list и lengths имеют одинаковую длину. j чередуется: 5,4,5,4,5, и функция разделения работает с первыми двумя чередованиями, то есть разбивает первый i списка на 5 и 4, НО на следующей итерации он разбивает его на 4,4 , 1. : \ Пожалуйста, ответьте, если вы хотите, чтобы я объяснил больше (задайте новый вопрос) - person Mike Issa; 05.02.2016

Если вас не волнует порядок ...

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

list[::2] получает каждый второй элемент в списке, начиная с 0-го элемента.
list[1::2] получает каждый второй элемент в списке, начиная с 1-го элемента.

person sentythee    schedule 13.06.2011
comment
Тщательно называйте arg list с затенением list(...) встроенного. Я видел, как lst и list_ обычно используются, чтобы избежать этого. - person Taylor Edmiston; 27.02.2017
comment
это кажется наиболее питоническим (игнорируя неправильное именование) - person Tjorriemorrie; 14.10.2017

Вот общее решение, разделить arr на счетную часть

def split(arr, count):
     return [arr[i::count] for i in range(count)]
person Chris Song    schedule 20.07.2012
comment
При этом теряется порядок списка - person Timmah; 20.09.2018

Использование нарезки списка. Синтаксис в основном my_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]

Чтобы получить первую половину списка, вы отрезаете от первого индекса до len(i)//2 (где // - целочисленное деление, поэтому _5my_list[start_index:end_index]6_1.5`):

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

..и поменяйте местами значения, чтобы получить вторую половину:

>>> i[len(i)//2:]
[3, 4, 5]
person dbr    schedule 15.04.2009
comment
как насчет нечетных списков len) - person N997; 01.05.2019
comment
@ N997 Код все еще должен работать; вы просто получаете разное количество элементов в каждом списке. Допустим, список состоит из трех элементов, оператор деления сводит результат к нулю, поэтому 3//2 дает 1, затем вы получаете i[:1], что дает [0], и i[1:], что дает [1, 2] - person dbr; 16.05.2019

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

 return (B,C)

Я тестировал, и двойная косая черта требуется для принудительного деления int в python 3. Мой исходный пост был правильным, хотя по какой-то причине wysiwyg сломался в Opera.

person Stefan Kendall    schedule 15.04.2009
comment
он не обрабатывает нечетные len (A) - у вас есть решение для этого? - person N997; 01.05.2019

Если у вас большой список, лучше использовать itertools и написать функцию для получения каждой части по мере необходимости:

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

Вы можете использовать это как:

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

size = len(A) // 2

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

Результат:

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

Благодаря @thefourtheye и @ Беде Константинидес

person M.A. Heshmat Khah    schedule 30.12.2018

Существует официальный рецепт Python для более обобщенного случая разделения массива на более мелкие массивы размером 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)

Этот фрагмент кода взят со страницы страницы документации python itertools.

person Jonathan Berger    schedule 21.04.2011

Это похоже на другие решения, но немного быстрее.

# 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:]
person Ruslanas Balčiūnas    schedule 27.05.2014
comment
Умное использование двоичного сдвига! - person Janusz Skonieczny; 16.07.2020

Спустя 10 лет .. Подумал - а почему бы не добавить еще:

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

Хотя приведенные выше ответы более или менее верны, вы можете столкнуться с проблемами, если размер вашего массива не делится на 2, поскольку в результате a / 2, нечетное значение, является плавающим в python 3.0, а в более ранней версии, если вы указываете from __future__ import division в начале вашего скрипта. В любом случае лучше использовать целочисленное деление, то есть a // 2, чтобы получить "прямую" совместимость вашего кода.

person user91259    schedule 15.04.2009

С подсказками от @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)
person PunjCoder    schedule 02.08.2012

Еще один подход к этой проблеме в 2020 году ... Вот обобщение проблемы. Я интерпретирую «разделить список пополам» как ... (т.е. только два списка, и не должно быть перетекания в третий массив в случае нечетного и т. Д.). Например, если длина массива равна 19, а деление на два с использованием оператора // дает 9, в результате мы получим два массива длиной 9 и один массив (третий) длиной 1 (итого, всего три массива). Если мы хотим, чтобы общее решение давало два массива все время, я предполагаю, что мы довольны результирующими двойными массивами, которые не равны по длине (один будет длиннее другого). И что предполагается, что порядок смешанный (в данном случае чередующийся) - это нормально.

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

Эта концепция работает для любого количества разделов списка по вашему желанию (вам придется настроить код в зависимости от того, сколько частей списка вы хотите). И довольно просто интерпретировать. Чтобы ускорить процесс, вы даже можете написать этот цикл на cython / C / C ++, чтобы ускорить процесс. Опять же, я пробовал этот код на относительно небольших списках ~ 10 000 строк, и он завершается за доли секунды.

Всего два цента.

Спасибо!

person aaronlhe    schedule 28.05.2020

Общий список решения разбит на n частей с проверкой параметров:

def sp(l,n):
    # split list l into n parts 
    if l: 
        p = len(l) if n < 1 else len(l) // n   # no split
        p = p if p > 0 else 1                  # split down to elements
        for i in range(0, len(l), p):
            yield l[i:i+p]
    else:
        yield [] # empty list split returns empty list
person Jacek Błocki    schedule 26.04.2021

person    schedule
comment
Я думаю, вы забыли разделить на 2 шага. :) - person Stefan Kendall; 15.04.2009
comment
Будьте осторожны, используйте вместо этого целочисленное деление //, как уже говорили другие. - person Stack; 26.11.2020