【问题标题】:Replacing every 2nd element in the list替换列表中的每个第二个元素
【发布时间】:2015-02-12 05:29:21
【问题描述】:

我有一个二维列表:

[[5, 80, 2, 57, 5, 97], [2, 78, 2, 56, 6, 62], [5, 34, 3, 54, 6, 5, 2, 58, 5, 61, 5, 16]]

我需要从第一个元素开始每隔一个元素将其更改为 0。所以它应该是这样的:

[[0, 80, 0, 57, 0, 97], [0, 78, 0, 56, 0, 62], [0, 34, 0, 54, 0, 5, 0, 58, 0, 61, 0, 16]]

我使用的算法:

for i in tempL: 
    for j, item in enumerate(i):
        if i.index(item) % 2 == 0:
            print('change, index:'),
            print(i.index(item))
            i[j] = 0
        else:
            print('not change, index:'),
            print(i.index(item))

但我得到的是这样的:

change, index: 0
not change, index: 1
change, index: 2
not change, index: 3
change, index: 4
not change, index: 5
change, index: 0
not change, index: 1
change, index: 2
not change, index: 3
change, index: 4
not change, index: 5
change, index: 0
not change, index: 1
change, index: 2
not change, index: 3
change, index: 4
not change, index: 5
change, index: 6
not change, index: 7
not change, index: 5
not change, index: 9
not change, index: 5
not change, index: 11
[[0, 80, 0, 57, 0, 97], [0, 78, 0, 56, 0, 62], [0, 34, 0, 54, 0, 5, 0, 58, 5, 61, 5, 16]]

有些元素没有改变,这是因为(我添加了 index print 来查看)它认为这些元素的索引是 7 和 9 出于某种原因。怎么回事,因为找了这么久的bug还是找不到..

我仔细检查了,列表中没有多余的空格或任何内容。

【问题讨论】:

  • 你为什么使用i.index?你不是说j吗?

标签: python


【解决方案1】:

只是为了加我的两分钱:

使用模运算符

mylist= [[5, 80, 2, 57, 5, 97], [2, 78, 2, 56, 6, 62], [5, 34, 3, 54, 6, 5, 2, 58, 5, 61, 5, 16]]

for i,n in enumerate(mylist):
    for j,m in enumerate(n):
        if j % 2 == 0:
            mylist[i][j] = 0

print mylist

输出:

[[0, 80, 0, 57, 0, 97], [0, 78, 0, 56, 0, 62], [0, 34, 0, 54, 0, 5, 0, 58, 0, 61, 0, 16]]

【讨论】:

    【解决方案2】:

    嗯,这个任务应该是显而易见的。使用切片分配!您需要分配一个零数组,即半长。要创建一个,只需将单个元素数组与值相乘:

    for l in tempL: 
        l[::2] = [0] * ((len(l)+1)/2)
    

    或者使用来自 itertools 的repeat(不幸的是,这对于小数组来说要慢两倍):

    from itertools import repeat
    
    for l in tempL: 
        l[::2] = repeat(0,(len(l)+1)/2)
    

    【讨论】:

    • 我尝试过切片,但没有弄清楚如何正确使用它。我也完全不明白你等式的后半部分。
    • 我很好奇并做了一些时间测试,这个答案中的第一个方法比理解快一个数量级(加) - 并且 缩放 更长的子列表更好。 @estranged - 左侧的 advanced 切片分配需要右侧的可迭代对象。右侧创建一个零列表,其中包含足够的分配项。 @Arpegius - 我认为您不需要 +1 来确定所需的零数。
    • @wwii 是的,你需要+1,就好像有奇数个元素你需要一个多半。如果你从第二个开始为[1::2],那么它将没有+1
    • 获取切片长度的更重言式的方法是l[::2] = [0] * len(l[::2])
    • @kojiro:创建一个全新的列表对象。在内存上计算长度要容易得多。
    【解决方案3】:

    作为一种更 Pythonic 的方式,您可以只使用列表推导:

    >>> l=[[5, 80, 2, 57, 5, 97], [2, 78, 2, 56, 6, 62], [5, 34, 3, 54, 6, 5, 2, 58, 5, 61, 5, 16]]
    >>> l=[[t if k%2 else 0 for k,t in enumerate(i)] for i in l]
    >>> l
    [[0, 80, 0, 57, 0, 97], [0, 78, 0, 56, 0, 62], [0, 34, 0, 54, 0, 5, 0, 58, 0, 61, 0, 16]]
    

    【讨论】:

    • 所以我只需将l 更改为我的列表名称?即使您的代码看起来不错,它也没有为我做任何事情。
    • @estranged 我没有看到任何错过代码的原因,请注意我的答案是在 shell 中,如果你在文本编辑器中编写代码,你需要打印它!!!
    • 哦,是的,我需要为此分配列表!这是非常好的。
    • @estranged 不客气!您无需创建新列表,只需将其分配给 l!
    • 甚至[[t if k%2 else 0 for k,t in enumerate(i)] for i in l]k%2 有一个布尔值。
    【解决方案4】:

    我认为你的算法是正确的。你只是犯了一个逻辑错误。通过使用i.index,您每次都在内部列表中搜索该值。这不仅昂贵,而且对重复值很敏感。

    for i in tempL: 
        for j, item in enumerate(i):
            # if i.index(item) % 2 == 0: oops
            if j % 2 == 0:
                print('change, index:'),
                print(i.index(item))
                i[j] = 0
            else:
                print('not change, index:'),
                print(i.index(item))
    

    【讨论】:

      猜你喜欢
      • 2020-01-10
      • 1970-01-01
      • 2019-06-27
      • 1970-01-01
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多