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


150

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

Так что если у меня есть массив:

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

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

B = [0,1,2]

C = [3,4,5]

Ответы:


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

70
Вы должны форсировать деление int в Python 3. // требуется.
Стефан Кендалл

4
Хорошее решение, спасибо. Он также работает с дробями, такими как 80/20 в Python3B = A[:(len(A) // 10) * 8] C = A[(len(A) // 10) * 8:]
Gergely M

87

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

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

РЕДАКТИРОВАТЬ 2 : обновить пост снова на основе информативных комментариев 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
Когда список не делится равномерно (например, split_list ([1,2,3], 2)), это фактически возвращает списки wanted_parts + 1.
Брайан

3
Я думаю, что лучшим способом было бы: length = len (alist); return [alist [i * length // wanted_parts: (i + 1) * length // wanted_parts] для i в диапазоне (wanted_parts)]. Таким образом, вы получаете равномерно возможный дистрибутив и всегда получаете точно нужные элементы_партов (даже пэды с [], если_парт_парели> len (A))
Брайан,

2
привет .. что означает символ "//" ??
Фразман

2
@Fraz - это встроенный комментарий. Игнорируйте "// wanted_parts" и "// wanted_parts", чтобы скрипт выполнялся.
PunjCoder

19
//означает целочисленное деление. Их не следует упускать из виду, поскольку они очень важны для выполнения этой работы.
Alphadelta14

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

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


1
Это прекрасно работает в моей ситуации, однако он добавляет каждый последний индекс каждого списка в свой собственный список. Трудно объяснить. Пожалуйста, ответьте, если вы можете помочь, и я объясню больше.
Майк Исса

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

1
также полезно конвертировать список в матрицу
mpgn

Это работает, но не совсем. Я использую эту функцию в цикле, и длины меняются. Другими словами: for i,j in zip(list,lengths): print(split(i,j)). listИ lengthsсписки имеют одинаковую длину. j чередуется: 5,4,5,4,5, и функция split работает на первых двух чередованиях, то есть разделяет первый iсписок на 5 и 4, НО на следующей итерации разделяет его на 4,4, 1. : \ Пожалуйста, ответьте, если вы хотите, чтобы я объяснил больше (отправьте новый вопрос)
Майк Исса

15

Если вы не заботитесь о заказе ...

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

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


4
Тщательно называйте арг listс затенением list(...)встроенного. Я видел lstи list_использовал обычно, чтобы избежать этого.
Тейлор

3
это кажется самым питоническим (игнорируя неправильное наименование)
Tjorriemorrie


11

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

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

Это теряет порядок списка
Тимма

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

 return (B,C)

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


он не обрабатывает нечетные len (A) - у вас есть решение для этого?
N997

6

Существует официальный рецепт 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 .


6

Использование списка нарезки . Синтаксис в основном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(где //целочисленное деление - так 3//2 will give the floored result of1 , instead of the invalid list index of1,5`):

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

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

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

как насчет странных списков
Лен

@ N997 Код все еще должен работать; вы просто в конечном итоге с различным количеством элементов в каждом списке. Допустим, список состоит из трех пунктов, оператор деления определяет результат, который он 3//2дает 1, а затем вы получаете то, i[:1]что дает, [0]а i[1:]что дает[1, 2]
dbr

3

Если у вас большой список, лучше использовать 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 и @Bede Constantinides


3

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

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

2

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



0

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

Еще один взгляд на эту проблему в 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 ++, чтобы ускорить процесс. Опять же, я попробовал этот код в сравнительно небольших списках ~ 10000 строк, и он заканчивается за доли секунды.

Просто мои два цента.

Спасибо!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.