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


150

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

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

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

我将能够得到:

B = [0,1,2]

C = [3,4,5]

Answers:


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中强制进行int除法。//是必需的。
Stefan Kendall,2009年

4
好的解决方案,谢谢。它也适用于Python3中的80/20之类的分数B = 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)),这实际上将返回wanted_pa​​rts + 1列表。
布赖恩

3
我认为更好的方法是:length = len(alist); 返回[alist [i * length // wanted_pa​​rts:(i + 1)* length // wanted_pa​​rts] for range in(wanted_pa​​rts)]。这样一来,您将获得尽可能均匀的分配,并且始终获得完全通缉的物品(如果通缉的物品> len(A),甚至可以使用[]填充)
Brian

2
嗨..符号“ //”是什么意思?
frazman 2012年

2
@Fraz它的意思是内联注释。忽略“ // wanted_pa​​rts”和“ // wanted_pa​​rts”以使脚本执行。
PunjCoder

19
//表示整数除法。不应该将它们排除在外,因为它们在完成这项工作中非常重要。
Alphadelta14 2013年

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 2015年

这行得通,但并不完全。我在循环中使用此函数,并且长度各不相同。换句话说:for i,j in zip(list,lengths): print(split(i,j))。在listlengths列表的长度相同。j是交替的:5、4、5、4、5,并且split函数作用于前两个交替,即它将ilist 的第一个分别除以5和4,但在下一次迭代时将其拆分为4,4, 1。:\请回复,如果你想我解释更多的(发布一个新的问题)
迈克·伊萨

15

如果您不在乎订单...

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

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


4
仔细给arg命名,list并使其list(...)内建阴影。我已经看到lstlist_经常使用它来避免这种情况。
泰勒·埃德米斯顿

3
这感觉最pythonic(忽略不正确的命名)
Tjorriemorrie


11

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

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)

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


它不处理奇数len(A)-您对此有解决方案吗?
N997,5

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 doc页面


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,19年

@ 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 / 2odd,在python 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,并使用//运算符将其除以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行)上尝试了此代码,并且在不到一秒的时间内完成了代码。

只是我的两分钱。

谢谢!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.