将列表拆分为较小的列表(一分为二)

问题:将列表拆分为较小的列表(一分为二)

我正在寻找一种轻松地将python列表分成两半的方法。

这样,如果我有一个数组:

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

我将能够得到:

B = [0,1,2]

C = [3,4,5]

I am looking for a way to easily split a python list in half.

So that if I have an array:

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

I would be able to get:

B = [0,1,2]

C = [3,4,5]

回答 0

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)
A = [1,2,3,4,5,6]
B = A[:len(A)//2]
C = A[len(A)//2:]

If you want a function:

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)

回答 1

一些通用的解决方案(您可以指定所需的零件数量,而不仅仅是“分成两半”):

编辑:更新后的帖子以处理奇数列表长度

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)

A little more generic solution (you can specify the number of parts you want, not just split ‘in half’):

EDIT: updated post to handle odd list lengths

EDIT2: update post again based on Brians informative comments

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

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

n -结果数组的预定义长度

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

n – the predefined length of result arrays


回答 3

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]]
def split(arr, size):
     arrs = []
     while len(arr) > size:
         pice = arr[:size]
         arrs.append(pice)
         arr   = arr[size:]
     arrs.append(arr)
     return arrs

Test:

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

result:

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

回答 4

如果您不在乎订单…

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

list[::2]从第0个元素开始获取列表中的每个第二个元素。
list[1::2]从第一个元素开始获取列表中的第二个元素。

If you don’t care about the order…

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

list[::2] gets every second element in the list starting from the 0th element.
list[1::2] gets every second element in the list starting from the 1st element.


回答 5

B,C=A[:len(A)/2],A[len(A)/2:]

B,C=A[:len(A)/2],A[len(A)/2:]


回答 6

这是一个常见的解决方案,将arr分为count部分

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

Here is a common solution, split arr into count part

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

回答 7

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

 return (B,C)

我进行了测试,在python 3中强制进行int分割需要使用双斜杠。我的原始帖子是正确的,尽管所见即所得由于某种原因在Opera中中断了。

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

 return (B,C)

I tested, and the double slash is required to force int division in python 3. My original post was correct, although wysiwyg broke in Opera, for some reason.


回答 8

对于将数组拆分为较小的较小数组的更普遍的情况,有一个官方的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 doc页面

There is an official Python receipe for the more generalized case of splitting an array into smaller arrays of size 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)

This code snippet is from the python itertools doc page.


回答 9

使用列表切片。语法基本上是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]

Using list slicing. The syntax is basically 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]

To get the first half of the list, you slice from the first index to len(i)//2 (where // is the integer division – so 3//2 will give the floored result of1, instead of the invalid list index of1.5`):

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

..and the swap the values around to get the second half:

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

回答 10

如果列表很大,最好使用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

If you have a big list, It’s better to use itertools and write a function to yield each part as needed:

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

You can use this like:

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

size = len(A) // 2

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

The output is:

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

Thanks to @thefourtheye and @Bede Constantinides


回答 11

10年后..我想-为什么不加上另一个:

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

10 years later.. I thought – why not add another:

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

回答 12

虽然上述答案或多或少是正确的,但是如果您的数组大小不能被2整除,则可能会遇到麻烦,因为,结果为a / 2odd,在python 3.0中为浮点数,在较早的版本中为from __future__ import division在脚本的开头指定。无论如何,您最好进行整数除法,即a // 2为了获得代码的“前向”兼容性。

While the answers above are more or less correct, you may run into trouble if the size of your array isn’t divisible by 2, as the result of a / 2, a being odd, is a float in python 3.0, and in earlier version if you specify from __future__ import division at the beginning of your script. You are in any case better off going for integer division, i.e. a // 2, in order to get “forward” compatibility of your code.


回答 13

这与其他解决方案相似,但速度更快。

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

This is similar to other solutions, but a little faster.

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

回答 14

来自@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)

With hints from @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)

回答 15

#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       
#for python 3
    A = [0,1,2,3,4,5]
    l = len(A)/2
    B = A[:int(l)]
    C = A[int(l):]       

回答 16

在2020年对该问题的另一种看法…这是问题的概括。我将“将列表分为两半”解释为..(即仅两个列表,并且如果出现奇数等,则不会溢出到第三数组)。例如,如果数组长度为19,并使用//运算符将其除以2,则结果为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行)上尝试了此代码,并且在不到一秒的时间内完成了代码。

只是我的两分钱。

谢谢!

Another take on this problem in 2020 … Here’s a generalization of the problem. I interpret the ‘divide a list in half’ to be .. (i.e. two lists only and there shall be no spillover to a third array in case of an odd one out etc). For instance, if the array length is 19 and a division by two using // operator gives 9, and we will end up having two arrays of length 9 and one array (third) of length 1 (so in total three arrays). If we’d want a general solution to give two arrays all the time, I will assume that we are happy with resulting duo arrays that are not equal in length (one will be longer than the other). And that its assumed to be ok to have the order mixed (alternating in this case).

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

This concept works for any amount of list partition as you’d like (you’d have to tweak the code depending on how many list parts you want). And is rather straightforward to interpret. To speed things up , you can even write this loop in cython / C / C++ to speed things up. Then again, I’ve tried this code on relatively small lists ~ 10,000 rows and it finishes in a fraction of second.

Just my two cents.

Thanks!