Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中的列表中创建列表_Python_List - Fatal编程技术网

在Python中的列表中创建列表

在Python中的列表中创建列表,python,list,Python,List,我有一个名为values的列表,其中包含一系列数字: values = [0, 1, 2, 3, 4, 5, ... , 351, 0, 1, 2, 3, 4, 5, 6, ... , 750, 0, 1, 2, 3, 4, 5, ... , 559] 我想创建一个新列表,其中包含从0到数字的元素列表 比如: new_values = [[0, 1, 2, ... , 351], [0, 1, 2, ... , 750], [0, 1, 2, ... , 559]] 我所做的代码是: sta

我有一个名为values的列表,其中包含一系列数字:

values = [0, 1, 2, 3, 4, 5, ... , 351, 0, 1, 2, 3, 4, 5, 6, ... , 750, 0, 1, 2, 3, 4, 5, ... , 559]
我想创建一个新列表,其中包含从0到数字的元素列表

比如:

new_values = [[0, 1, 2, ... , 351], [0, 1, 2, ... , 750], [0, 1, 2, ... , 559]]
我所做的代码是:

start = 0
new_values = []
for i,val in enumerate(values): 
    if(val == 0):
        new_values.append(values[start:i]) 
        start = i
但是,它返回的是:

new_values = [[], [0, 1, 2, ... , 750], [0, 1, 2, ... , 559]]

如何修复我的代码?这将是一个很大的帮助。

您可以使用
itertools对元素进行分组。groupby
基于
0
(这是错误的)的存在,并提取
0
之间的子列表,同时用列表添加缺少的
0

 [[0]+list(g) for k, g in groupby(values, bool) if k]
例如:

>>> from itertools import groupby
>>> values = [0, 1, 2, 3, 4, 5 , 351, 0, 1, 2, 3, 4, 5, 6, 750, 0, 1, 2, 3, 4, 559]
>>> [[0]+list(g) for k, g in groupby(values, bool) if k]
[[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 559]]

因此,您编写的代码的问题在于,它在开头包含一个空的
列表
,而忽略了最后一个子
列表
。最简单的解决方案是:

  • 更改测试以避免附加第一个
    列表
    (当
    i
    为0时),例如,如果val==0和i!=0:

  • 在循环退出后追加最后一个组

  • 结合这两个修复,您将拥有:

    start = 0
    new_values = []
    for i,val in enumerate(values): 
        if val == 0 and i != 0:  # Avoid adding empty list
            new_values.append(values[start:i]) 
            start = i
    if values:  # Handle edgecase for empty values where nothing to add
        new_values.append(values[start:])  # Add final list
    
    我打算添加cleaner
    groupby
    解决方案,它避免了
    列表开始/结束的特殊情况,但是,我会让您参考他的答案

    有点令人惊讶的是,这实际上似乎是最快的解决方案,渐进地,代价是要求输入是一个
    列表
    (其中一些其他解决方案可以接受任意iterables,包括不可能索引的纯迭代器)

    用于比较(为了简洁和在现代Python上获得最佳性能,使用Python 3.5额外的解包泛化,并使用
    int
    的隐式布尔值避免与
    0
    进行比较,因为它相当于
    int
    输入,但使用隐式布尔值要快得多):

    使用
    ipython
    6.1的
    %timeit
    magic在Python 3.6、Linux x64上计时:

    >>> values = [*range(100), *range(50), *range(150)]
    >>> %timeit -r5 method1(values)
    12.5 μs ± 50.6 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    >>> %timeit -r5 method2(values)
    16.9 μs ± 54.9 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    >>> %timeit -r5 method3(values)
    13 μs ± 18.9 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    >>> %timeit -r5 method4(values)
    16.7 μs ± 9.51 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    >>> %timeit -r5 method5(values)
    18.2 μs ± 25.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)
    
    摘要:

    批量分割运行的解决方案
    method1
    method3
    是最快的,但取决于输入是一个序列(如果返回类型必须是
    list
    ,那么输入也必须是
    list
    ,或者必须添加转换)

    groupby
    解决方案
    method2
    method5
    稍慢一些,但通常非常简洁(像
    method5
    那样处理所有边缘情况不需要非常详细,也不需要显式的测试和检查LBYL模式)除了使用
    操作符.truth
    而不是
    bool
    之外,它们也不需要太多的黑客来让它们尽可能快地运行
    。这是必要的,因为由于一些奇怪的实现细节,CPython的
    bool
    构造函数非常慢(
    bool
    必须接受完整的变量,包括关键字,通过对象施工机械进行调度,这比
    操作符的成本要高很多。truth
    使用低开销路径,只接受一个位置参数并绕过对象施工机械);如果
    bool
    被用作
    函数而不是
    运算符。truth
    ,则运行时间增加一倍以上(对于
    方法2
    方法5
    ,分别为36.8μs和38.8μs)

    介于两者之间的是更慢但更灵活的方法(处理任意输入的可重用项,包括迭代器、处理没有特殊大小写的0的运行等)。使用逐项
    追加
    s
    方法4
    )。问题是,获得最大性能需要更多的详细代码(因为需要避免重复索引和方法绑定);如果
    method4
    的循环更改为更加简洁:

    for val in values:
        if not val:
            new_values.append([])
        new_values[-1].append(val)
    
    由于反复索引
    new_值
    和反复绑定
    append
    方法的成本,运行时间增加了一倍以上(达到34.4μs)


    在任何情况下,就个人而言,如果性能不是绝对关键,我会使用
    groupby
    解决方案之一,使用
    bool
    作为
    键,以避免导入和不常见的API。如果性能更重要,我可能仍然使用
    groupby
    ,但交换
    operator.truth>
    作为
    函数
    ;当然,它的速度不如详细说明的版本快,但是对于了解
    groupby
    的人来说,它很容易理解,并且对于任何给定级别的边缘案例处理来说,它通常是最简洁的解决方案。

    您可以通过查找每个val所在的所有组来使用
    itertools.groupby
    ue小于在
    值中执行它的元素:

    import itertools
    values = [0, 1, 2, 3, 4, 5, 351, 0, 1, 2, 3, 4, 5, 6, 750, 0, 1, 2, 3, 4, 5, 559]
    new_vals = [[i[-1] for i in b] for a, b in itertools.groupby(enumerate(values), key=lambda x:x[-1] <= values[x[0]+1] if x[0]+1 < len(values) else False)]
    final_data = [new_vals[i]+new_vals[i+1] for i in range(0, len(new_vals), 2)]
    
    这应该起作用:

    values = [0, 1, 2, 3, 4, 5, 351, 0, 1, 2, 3, 4, 5, 6, 750, 0, 1, 2, 3, 4, 5, 559]
    new_values = []
    
    split_at = 0  # split the list when this value is reached
    
    idx = -1
    for value in values:
        if value == split_at:
            idx += 1
            new_values.append([])
    
        new_values[idx].append(value)
    
    输出:

    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    
    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    
    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    
    它还可以处理边槽

    我的方法比方法快一点,但也比方法慢一点:



    您也可以这样做:

    values = [0, 1, 2, 3, 4, 5, 351, 0, 1, 2, 3, 4, 5, 6, 750, 0, 1, 2, 3, 4, 5, 559]
    
    # Find all indices whose element is 0.
    indices = [index for index, value in enumerate(values) if value==0] + [len(values)]
    
    # Split the list accordingly
    values = [values[indices[i]:indices[i+1]] for i in range(len(indices)-1)]
    
    print(values)
    
    输出:

    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    
    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    
    [[0, 1, 2, 3, 4, 5, 351], [0, 1, 2, 3, 4, 5, 6, 750], [0, 1, 2, 3, 4, 5, 559]]
    

    次要说明:这假设
    0
    s从不背靠背出现,并且
    值总是以
    0
    开头。OP的示例遵循此规则,因此如果该规则得到保证,这是迄今为止最简单/最有效的解决方案。更正:因为
    bool
    具有荒谬的开销。将
    bool
    替换为
    operator.truth
    作为
    函数将消除该开销,使该成本与其他优化解决方案类似(稍微慢一点,但微不足道,其中
    bool
    可以使优化的非
    groupby
    解决方案所需的成本增加3倍).就个人而言,如果性能不重要,我会按原样使用此解决方案;如果性能重要,则切换到
    操作符。真相
    会让您以最小的复杂度变化获得较大的加速。是的,我知道
    bool
    比它应该的慢,直到我测试时才意识到速度慢了多少