แยกรายการออกเป็นรายการเล็ก ๆ (แบ่งครึ่ง)


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
คุณต้องบังคับให้มีการแบ่งส่วนใน Python 3 // เป็นสิ่งจำเป็น
Stefan Kendall

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)) สิ่งนี้จะส่งคืนรายการที่ต้องการ _parts + 1
Brian

3
วิธีที่ดีกว่าที่ฉันคิดว่าน่าจะเป็น: length = len (alist); ส่งคืน [alist [i * length // wants_parts: (i + 1) * length // wants_parts] สำหรับ i ในช่วง (want_parts)] ด้วยวิธีนี้คุณจะได้รับการแจกแจงเท่าที่จะเป็นไปได้และรับรายการอยากได้อย่างแน่นอน (แม้แต่แผ่นที่มี [] ถ้า want_parts> len (A))
Brian

2
สวัสดี .. สัญลักษณ์ "//" หมายถึงอะไร?
frazman

2
@Fraz มันหมายถึงความคิดเห็นแบบอินไลน์ เพิกเฉย "// want_parts" และ "// want_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
สิ่งนี้ใช้งานได้ดีในสถานการณ์ของฉันอย่างไรก็ตามมันผนวกท้ายดัชนีสุดท้ายของแต่ละรายการไว้ในรายการของตัวเอง ยากที่จะอธิบาย. โปรดตอบกลับหากคุณสามารถช่วยได้และฉันจะอธิบายเพิ่มเติม
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

ทดสอบ:

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 : \ โปรดตอบกลับหากคุณต้องการให้ฉันอธิบายเพิ่มเติม (โพสต์คำถามใหม่)
Mike Issa

15

หากคุณไม่สนใจเกี่ยวกับการสั่งซื้อ ...

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

list[::2]รับทุก ๆ องค์ประกอบที่สองในรายการโดยเริ่มจากองค์ประกอบที่ 0
list[1::2]รับทุก ๆ องค์ประกอบที่สองในรายการโดยเริ่มจากองค์ประกอบที่ 1


4
ระวังการตั้งชื่อหาเรื่องlistด้วยเงาในlist(...)ตัว ฉันเคยเห็นlstและlist_ใช้กันทั่วไปเพื่อหลีกเลี่ยงมัน
Taylor Edmiston

3
สิ่งนี้ให้ความรู้สึกที่
ไพเราะ


11

นี่คือวิธีแก้ปัญหาทั่วไปแบ่งออกเป็นส่วนที่นับเป็น

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

สิ่งนี้จะสูญเสียลำดับของรายการ
Timmah

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

 return (B,C)

ฉันทดสอบแล้วและต้องใช้เครื่องหมายทับสองครั้งเพื่อบังคับให้มีการหาร int ใน python 3 โพสต์ดั้งเดิมของฉันถูกต้องแม้ว่า wysiwyg จะพังใน Opera ด้วยเหตุผลบางประการ


มันไม่ได้จัดการกับ len len (A) - คุณมีทางออกสำหรับสิ่งนั้นหรือไม่?
N997

6

มีอย่างเป็นทางการหลาม receipe 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)

รหัสนี้เป็นตัวอย่างข้อมูลจากหน้า doc หลาม 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]

สิ่งที่เกี่ยวกับรายการ len แปลก)
N997

@ 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การเป็นคี่เป็นทุ่นในหลาม 3.0 และในเวอร์ชันก่อนหน้าถ้าคุณ ระบุfrom __future__ import divisionที่จุดเริ่มต้นของสคริปต์ของคุณ คุณไม่ว่าในกรณีใดจะดีกว่าสำหรับการหารจำนวนเต็มเช่นa // 2เพื่อให้เข้ากันได้กับโค้ดของคุณ


2

คล้ายกับโซลูชันอื่น ๆ แต่เร็วกว่าเล็กน้อย

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

การใช้ระบบเปลี่ยนไบนารีอย่างชาญฉลาด!
Janusz Skonieczny

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 แถวและมันก็เสร็จในเสี้ยววินาที

แค่สองเซ็นต์ของฉัน

ขอบคุณ!

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.