【问题标题】:Detect If Item is the Last in a List [duplicate]检测项目是否是列表中的最后一个
【发布时间】:2017-02-10 01:23:59
【问题描述】:

我正在使用 Python 3,并试图检测一个项目是否是列表中的最后一个,但有时会重复。这是我的代码:

a = ['hello', 9, 3.14, 9]
for item in a:
    print(item, end='')
    if item != a[-1]:
        print(', ')

我想要这个输出:

hello,
9,
3.14,
9

但是我得到了这个输出:

hello, 
93.14, 
9

我明白为什么会得到我不想要的输出。 如果我仍然可以使用循环,我会更喜欢,但我可以解决它们。 (我想在更复杂的代码中使用它)

【问题讨论】:

  • 不使用循环:print(*a, sep=',\n')
  • @MartijnPieters 哇,谢谢。为什么最后一项不加逗号?
  • @nedla2004:因为sep 是元素之间的分隔符end 是结束符,在最后一个元素之后。
  • 因为sep 用在元素之间,而不是之后。

标签: python list python-3.x


【解决方案1】:

虽然这些答案可能适用于 OP 的特定情况,但我发现它们对于更广泛的应用并不令人满意。

这里是我能想到/看到的方法以及它们各自的时间。

索引方法

urlist_len = len(urlist)-1
for x in urlist:
    if urlist.index(x) == urlist_len:
        pass

负片法

for x in urlist:
    if x == urlist[-1]:
        pass

枚举方法

urlist_len = len(urlist)-1
for index, x in enumerate(urlist):
    if index == urlist_len:
        pass

以下是一些不同方法的时间安排:

╔════════════════════════════════════════════════════════════════╗
║                       Timing Results (s)                       ║
╠═══════════════════════╦════╦═════════╦════════╦═══════╦════════╣
║ List size             ║ 20 ║ 200     ║ 2000   ║ 20000 ║ 200000 ║
╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣
║                       ║ 0  ║ 0.0006  ║ 0.051  ║ 5.2   ║ 560    ║
║ Index Method          ║    ║         ║        ║       ║        ║
╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣
║                       ║ 0  ║ 0       ║ 0.0002 ║ 0.003 ║ 0.034  ║
║ Negative Slice Method ║    ║         ║        ║       ║        ║
╠═══════════════════════╬════╬═════════╬════════╬═══════╬════════╣
║ Enumerate Method      ║ 0  ║ 0.00004 ║ 0.0005 ║ 0.016 ║ 0.137  ║
╚═══════════════════════╩════╩═════════╩════════╩═══════╩════════╝

注意:值

如您所见,索引方法总是较慢,并且随着列表大小的增加,它只会以指数方式变差。我看不出有任何理由使用它。 Negative slice 方法在所有情况下都是最快的,但如果您的列表中有重复的项目,它会给您一个误报。此外,负切片方法要求您正在迭代的序列支持索引。因此,如果列表中有重复项(或不支持索引的序列),请使用 fast-but-not-fastest enumerate 方法。

编辑:正如评论员所说,计算循环内列表的长度并不理想。使用这些知识,我能够将枚举方法(目前未反映在表格中)减少 35%。


tldr:如果所有元素都是唯一对象并且序列支持索引,则使用负切片,否则使用枚举方法

【讨论】:

  • 不确定它是否会有很大的不同,但您可以在循环外进行 len(urlist)-1 计算以提高 indexenumerate 方法的性能
  • @maxedison 你说得对。在enumerate 方法中,我能够剃掉约 35%。
  • 我认为前两个可以通过使用for x in urlist[:-1]: 来加速除最后一个之外的所有元素(循环中没有if 语句检查它),然后是处理代码的代码循环外的最后一个元素。 enumerate() 方法也可以做类似的事情。
  • 关于“负片”选项的快速说明,如果您输入了一堆相似的值,比如测试分数,并且您的列表中有 2 个相同的值,您可能会提前退出循环。
  • 这是一个教科书示例,说明 SO 答案应该是什么。出色的工作@Mattwmaster58
【解决方案2】:

不要尝试检测您是否在最后一项,而是在打印下一项时打印逗号和换行符(只需要检测您是否在第一项):

a = ['hello', 9, 3.14, 9]
for i, item in enumerate(a):
    if i:  # print a separator if this isn't the first element
        print(',')
    print(item, end='')
print()  # last newline

enumerate() 函数为每个元素添加一个计数器(参见What does enumerate mean?),并且if i: 对除0(第一个元素)之外的所有计数器值都为真。

或者使用print()插入分隔符:

print(*a, sep=',\n')

sep 值插入每个参数之间(*aa 中的所有值作为单独的参数应用,请参阅 What does ** (double star) and * (star) do for parameters?)。这比使用print(',n'.join(map(str, a))) 更有效,因为它不需要先构建一个全新的字符串对象。

【讨论】:

    【解决方案3】:

    如果您真的只是想将元素加入逗号+换行符分隔的字符串,那么使用str.join 方法会更容易:

    elements = ['hello', 9, 3.14, 9]
    s = ',\n'.join(str(el) for el in elements)
    # And you can do whatever you want with `s` string:
    print(s)
    

    【讨论】:

    • @MartijnPieters,当然,但是print 会打印您的字符串,并且您有可能稍后想要操作该字符串。
    • 你也可以使用地图! print(',\n'.join(map(str,elements)))
    【解决方案4】:

    您没有得到预期的输出,因为您在代码中说:“嘿,python,如果当前元素不等于最后一个元素,则打印一个逗号。”

    第二个元素 9 等于最后一个元素,因此不打印逗号。

    检查最后一个元素的正确方法是检查元素的索引:

    a = ['hello', 9, 3.14, 9]
    for item in a:
        print(item, end='')
        if a.index(item) != len(a)-1: #<--------- Checking for last element here
            print(', ')
    

    (另外,这可能会引发值错误。您也应该检查一下。)

    【讨论】:

      【解决方案5】:

      测试索引值是否为列表长度- 1

      像这样:

          if item != (len(a) - 1):
              #whatever you wanted to do
      
          #or, if you want the index to be the last...
          if item == (len(a) - 1):
              #whatever you wanted to do
      

      【讨论】:

        【解决方案6】:

        如果您只是想查看项目是否在列表中(或任何列表中的任何项目)中,您可以尝试使用函数来检查项目是否在列表中的最后。

        a = ['hello', 9, 3.14, 9]
        def is_last(alist,choice):
                if choice == alist[-1]:
                    print("Item is last in list!")
                    return True
                else:
                    print("Item is not last")
                    return False
        
        if is_last(a,9) == True:
            <do things>
        
        else:
            <do other things>
        

        【讨论】:

        • 是的,Python 使用负索引在列表中从右到左计数。
        • 对于a[1]a[3]is_last(a, 9) 将返回True 两次。另外,不要在if 语句中使用== True,将真实性测试直接留给if
        • Martijn 是正确的,比较值不一定找到列表的末尾。
        • 我同意 Martijn 和 kmarsh 的观点。如果列表有重复值,“end”会更早找到,而不是在结尾。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-26
        • 1970-01-01
        • 2022-08-24
        相关资源
        最近更新 更多