Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.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列表的子集,基于同一列表的元素组,pythonically_Python_Python 3.x_List - Fatal编程技术网

python列表的子集,基于同一列表的元素组,pythonically

python列表的子集,基于同一列表的元素组,pythonically,python,python-3.x,list,Python,Python 3.x,List,我有一个平面的数字列表,逻辑上是的,每组3个,其中每个三元组是(数字,被忽略,标志[0或1]),例如: [7,56,1,8,0,0,2,0,0,6,1,1,7,2,0,2,99,1] 我想(pythonically)处理此列表以根据“flag”的值创建一个新的数字列表:如果“flag”为1,则我需要“number”,否则为0。因此,上述清单将成为: [7,0,0,6,0,2] 我的初步尝试是: list = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]

我有一个平面的数字列表,逻辑上是,每组3个,其中每个三元组是(数字,被忽略,标志[0或1]),例如:

[7,56,1,8,0,0,2,0,0,6,1,1,7,2,0,2,99,1]

我想(pythonically)处理此列表以根据“flag”的值创建一个新的数字列表:如果“flag”为1,则我需要“number”,否则为0。因此,上述清单将成为:

[7,0,0,6,0,2]

我的初步尝试是:

list = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
numbers = list[::3]
flags = list[2::3]

result = []
for i,number in enumerate(numbers):
  result.append(number if flags[i] == 1 else 0)
这是可行的,但在我看来,应该有更好的方法从列表中清晰地提取元组。比如:

list = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
for (number, __, flag) in list:
    ...etc
但我似乎无法做到这一点

我可以循环浏览整个列表:

result = []
for i in range(0, len(list), 3):
    result.append(list[i] if list[i+2] == 1 else 0)
看起来更小更有效

我不清楚这里最好的选择是什么。如有任何建议,将不胜感激

注意:我已接受wim的回答:

[L[i]*L[i+2]表示范围内的i(0,len(L),3)]

但我想重申,wims和暗影突击队的反应都是有效的。我接受了wim基于简单性和清晰性的回答(在较小程度上,还接受了与Python2的兼容性,尽管ShadowRanger指出zip也在Py2中,所以这个基础是无效的)

暗影游侠的回答是:

[number if flag-else 0表示数字,u,zip中的标志(*[iter(mylist)]*3)]

也完全符合我的要求(提供元组),但有点晦涩,需要压缩。正如wim所指出的,ShadowRanger的答案非常适合于数据流,而不是固定列表

我还想指出,ShadowRanger的回答增加了对zip()的模糊使用(随着时间的推移,它会变得不那么模糊),但通过使用元组的命名值,增加了清晰度,因此这有点胜负

对于那些努力理解
zip(*[iter(mylist)]*3)]
的人来说,它创建了一个迭代器的三个副本,然后用于构造元组。因为它是同一个迭代器,所以每次使用都会推进迭代器,使元组完全符合我的要求

为了清晰和通用性,我也有点倾向于@ShadowRanger的解决方案的修改版本:

i = iter(mylist)
[number if flag else 0 for number, _, flag in zip(i, i, i)]

(对我来说,这似乎不那么晦涩)。

我认为最直接的方法是简单的列表理解:

>>> [L[i]*L[i+2] for i in range(0, len(L), 3)]
[7, 0, 0, 6, 0, 2]

或者考虑NUMPY,它对于这样的任务是强大的:

>>> import numpy as np
>>> a = np.array(L).reshape(-1, 3).T
>>> a
array([[ 7,  8,  2,  6,  7,  2],
       [56,  0,  0,  1,  2, 99],
       [ 1,  0,  0,  1,  0,  1]])
>>> a[0]*a[2]
array([7, 0, 0, 6, 0, 2])

由于您有逻辑三元组,您可以使用
iter
、序列乘法和
zip
来实现您的目标:

result = []
for number, _, flag in zip(*[iter(mylist)]*3):
    result.append(number if flag else 0)  # flag is only 1 or 0, so no need to compare it
将同一迭代器在
mylist
上解压为
zip
的三个参数;由于它是同一个迭代器,
zip
为第一个输出提取元素0、1和2,然后提取元素3、4和5,以此类推。然后循环将这三个元素解压为逻辑名称(使用
\uu
表示您不关心的值)

列表理解甚至可以是一行:

result = [number if flag else 0 for number, _, flag in zip(*[iter(mylist)]*3)]
虽然这有点难理解,意思是明智的

这种方法的优点是:

  • 它适用于任何iterable,而不仅仅是
    list
    s
  • 它的性能;输入只被遍历一次,任何切片解决方案都会对其进行多次遍历
  • 它使用有意义的名称,而不是索引偏移量的匿名幻数
  • 缺点:

  • zip(*[iter(mylist)]*3)
    有点神奇
  • 如果您的输入长度不是三的倍数,它将自动忽略数据(末尾的部分组被删除)
  • 注意:在任何类似于生产代码的情况下,不要内联
    zip
    /
    iter
    /unpack技巧。使用(或基于
    zip
    的变体)并调用:

    # Defined somewhere else for common use
    def grouper(iterable, n, fillvalue=None):
        "Collect data into fixed-length chunks or blocks"
        # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx"
        args = [iter(iterable)] * n
        return itertools.zip_longest(*args, fillvalue=fillvalue)
    
    for number, _, flag in grouper(mylist, 3):
    
    配方是经过测试和预测的,通过给它起一个名字,你可以使使用它的代码更加明显。

    我想这可能会奏效:

    >>> list_ = [7,56,1, 8,0,0, 2,0,0, 6,1,1, 7,2,0, 2,99,1]
    >>> [a if c == 1 else 0 for a,c in zip(list_[::3],list_[2::3])]
    ... 
     [7, 0, 0, 6, 0, 2]
    

    这两个字段看起来都很可靠——虽然我简化了,但flag字段是文本字段,所以乘法不是一个选项。但我认为你建议的基本解决方案在更一般的情况下有效。非常感谢。作为一个附带问题,如果可以通过您的第一个选项完成一个基本列表,那么我是否正确地假设使用numpy重构数组会大大降低效率?不一定-numpy通常比Python循环更大的数据更有效。但是,如果您混合使用文本和数字,那么numpy可能不是一个很好的选择-您可能希望进行预处理,将文本标志转换为数字标志,以获得使用numpy数组的效率收益。注意:基于简单性和清晰性(以及与python 2的兼容性),我接受了这个答案。@ShadowRanger的回答也很好;它完全符合我的想法(提供元组),但有点晦涩,需要压缩。正如wim所指出的,后者非常适合于数据流,而不是固定列表。@rabidtrantation:不反对接受这个列表,但需要注意的是:我的答案适用于Python 2。如果您从itertools import izip作为zip添加一个有条件的导入,那么它在Py2中的工作效率会更高(因此即使在Py2中,您也会得到一个懒惰的Py3样式
    zip
    ),或者如果您选择了这条路线,则将
    izip最长作为zip最长的
    ,但它在Py2上使用的是纯
    zip
    zip
    已经存在了很久,从Py2到Py3的唯一变化是Py2版本产生了
    list
    tuple
    s,Py3版本产生了
    tuple
    s的迭代器)。我认为你的建议比OP的原始代码要糟糕得多(不必要的复杂度)很好的解决方案;我也很喜欢使用zip带来的良好性能。现在我希望我能接受这两个答案。它们都很好。因为你有一个输入列表,它提供了通过索引进行O(1)访问的良好功能。不妨利用这一功能。