【问题标题】:Skip statements in case of last item in iterator在迭代器中的最后一项的情况下跳过语句
【发布时间】:2017-10-04 15:38:40
【问题描述】:

我想跳过 for 循环中的一些语句,以获取 dict 中的最后一个键值对。

让我们假设下一个 sn-p 是真正的程序:

a = { 'a': 1, 'b': 2, 'c': 3 } # I don't know the exact values, so can't test on them
for key, value in a.iteritems():
    # statements always to be performed

    # statements I want to skip when the current key, value pair is the last unprocessed pair in the dict.

    # maybe some more statements not to be skipped (currently not forseen, but might be added in the future)

# other statements in the program

这可能很简单,但我找不到。

好的,我可以使用 while 循环来编写它:

stop = False
b = a.iteritems()
next_key, next_value = b.next()
while True:
    key, value = next_key, next_value
    # do stuff which should be done always

    try:
        next_key, next_value = b.next()
    except StopIteration:
        stop = True
    else:
        # do stuff which should be done for everything but the last pair

    # the future stuff which is not yet forseen.

    if stop:
        break

但我认为这是丑陋的代码,因此我寻找一种在 for 循环中执行此操作的好方法。 这可能吗?

哦,是的:它需要适用于 python 2.7(而 python 2.5 将是一个奖励),因为这是我工作中的 python 版本(主要是 python 2.7)。

【问题讨论】:

  • 字典未排序。您确定要跳过最后一项吗?还是只有一件?
  • 最后一个,我的意思是for循环的最后一个,它可能不是最后一个定义的项目(所以它可能是 ('b', 2) 而不是 ('c', 3))。在那一刻,关键和价值不在乎。
  • 也许更清楚一点:它应该适用于任何可迭代的
  • 恕我直言,您无法使用for 循环使其适用于任何可迭代对象。
  • @MosesKoledoye 和 Jean-Francois Fabre:好吧,不如把它留在字典里,因为这是我现在使用的。

标签: python python-2.7 python-2.5


【解决方案1】:

由于它必须适用于任何可迭代对象,因此您不能依赖 len

为了能够使用 for 循环,我将创建一个辅助生成器函数,它会延迟 yield 直到它知道它是否是最后一个元素。

如果是最后一个元素,则返回True + key / value,否则返回False + key / value

概念证明:

a = { 'a': 1, 'b': 2, 'c': 3 }

def delayed_iterator(a):
    previous_v = None
    while True:
        v = next(a,None)
        if not v:
            yield True, previous_v
            break
        else:
            if previous_v:
                yield False, previous_v
            previous_v = v


for is_last, v in delayed_iterator(iter(a)):  # with iter, we make sure that it works with any iterable
    print(is_last,v,a[v])

输出是:

False a 1
False b 2
True c 3

【讨论】:

    【解决方案2】:

    您可以使用itertools.islice 获取除最后一项以外的所有项目:

    from itertools import islice
    
    a = { 'a': 1, 'b': 2, 'c': 3 }
    for key, value in islice(a.iteritems(), len(a)-1 if a else None):
        ...
    

    三元条件有助于处理 len(a)-1 给出否定结果的情况,即 dict 为空。

    【讨论】:

    • “它应该适用于任何可迭代的”。因此len是被禁止的。
    • 最后我找到了一个与这个答案背后的想法相一致的结构:for i, (k,v) in enumerate(a.iteritems()): if i != len(a) -1: # 做事
    • 现在看,这个解决方案很明显,我一开始就应该想到它。我想得太复杂了。
    【解决方案3】:

    python 字典中没有“first”或“last”键,因为它在遍历它时不保留其元素的插入顺序。

    但是,您可以使用 OrderedDict 并像这样识别最后一个元素:

    import collections
    
    a = collections.OrderedDict()
    a['a'] = 1
    a['b'] = 2
    a['c'] = 3
    
    for key, value in a.items():
        if(key != list(a.items())[-1][0]):
            # statements I want to skip when the current key, value pair is the last unprocessed pair in the dict.
    

    【讨论】:

    • 由于人们倾向于关注字典而不是 for 循环,我应该使用另一种可用于 for 循环的类型,因为它是最后一个值for-loop 遇到,如果是 dict,它并不关心该键值对是什么。只是它是 for 循环遇到的最后一个。对于列表 x=[1,2,3] 这将是 3,但对于 dict 它确实可以是任何东西。也许这可以清除一点。很抱歉造成混乱。
    【解决方案4】:

    首先,普通的字典是没有顺序的,所以你需要使用OrderedDict或者元组数组来代替。

    其次,为什么不排除您循环遍历的集合中的最后一个元素。

    import collections
    
    a = OrderedDict()
    # add stuff to a
    
    for key, value in a.items()[:-1]:
        # do something
    

    【讨论】:

    • 我必须为我的 for 循环中的所有项目执行大部分操作。只是不是最后一项(在这种情况下是一个字典条目,但可以是任何可迭代的)。
    • @Nemelis 当你甚至不知道最后一个元素会是什么时,跳过它的逻辑是什么?
    • 在这种情况下,这是对文件的一些处理,这也是最后一个字典对在其他地方完成的,因为对于最后一对,在文件处理需要之前还必须完成一些其他事情完成。同样,实际的对并不重要,只是它是 for 循环中的最后一对。
    猜你喜欢
    • 2023-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-21
    • 2018-10-22
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多