Розділити список на менші списки (розділити навпіл)


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

Трохи більш загальне рішення (ви можете вказати кількість потрібних деталей, а не просто розділити "навпіл"):

РЕДАКТУВАННЯ : оновлена ​​публікація, щоб обробити незвичайні довжини списку

EDIT2 : оновлення публікації знову на основі інформаційних коментарів 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)), він фактично поверне потрібні_частини + 1 списки.
Брайан

3
Кращим способом, на мою думку, був би: length = len (alist); повернути [alist [i * length // прагнув_parts: (i + 1) * length // прагнув_parts] для i в діапазоні (ht_parts)]. Таким чином ви отримуєте рівномірний можливий розподіл і завжди отримуєте точно потрібні елементи (навіть колодки з [], якщо want_parts> len (A))
Брайан

2
привіт .. що означає символ "//"
frazman

2
@Fraz Це означає як вбудований коментар. Ігноруйте "// ht_parts" та "// ht__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, і функція розбиття працює на перших двох чергуваннях, тобто розбиває перший 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 ++, щоб прискорити роботу. Потім знову я спробував цей код у відносно невеликих списках ~ 10 000 рядків, і він закінчується за частку секунди.

Всього два мої центи.

Дякую!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.