在Python中跳过列表中的元素

11

我是编程新手,正在尝试从codingbat.com开始解决问题。我遇到了这个问题:

给定一个数组,计算除了数组中有13的数以外的所有数字之和。如果数组中有13,则跳过它和紧随其后的数字。例如,[1,2,13,5,1]应该得出4(因为跳过了13和5)。

这是我目前的进展。我的问题是当有多个13时,我不知道该怎么做...而且我想高效地学习编程。你们能帮忙吗?(我正在使用Python 3.2)谢谢!

def pos(nums):
    for i in nums:
        if i == 13:
            return nums.index(13)
    return False

def sum13(lis):
    if pos(lis)!= False:
        return sum(lis[:pos(lis)])+sum(lis[pos(lis)+1:])
    else:
        return sum(lis)

1
你的例子应该返回 4,对吧?1+2+1 = 4。 - cheeken
2
@WillBuddha 我认为连续的13的行为有点模糊不清。一个13是否应该跳过后续13的影响? - cheeken
假设13不会跳过连续的13的影响,那么[13,13,1,4]将得到4。 - Terence Chow
如果 foo != False,那么这是多余的;只需使用 if foo: 即可。 - Wooble
你接受的答案在这里同样适用:http://codingbat.com/prob/p108886 - user5306470
7个回答

11

需要注意的一个棘手的问题是这样的:[1、13、13、2、3]

你也需要跳过2

def getSum(l):
    sum = 0
    skip = False
    for i in l:
         if i == 13:
             skip = True
             continue
         if skip:
             skip = False
             continue
         sum += i
    return sum

说明:

逐一检查列表中的每个项目。

每次你需要:

  • 首先检查它是否为13,如果是,那么您将标记skipTrue,以便您也可以跳过下一个项目。
  • 其次,您检查skip是否为True,如果是,则意味着它是13后面的项目,因此您也需要跳过此项目,并且您还需要将skip设置回False,以便您不会跳过下一个项目。
  • 最后,如果都不是上述情况,则将该值加到sum中。

你能向像我这样的新手解释一下这个迭代吗? - Terence Chow
啊,我没意识到如果跳过:暗示如果skip = True ...谢谢! - Terence Chow
啊,我喜欢这个答案,我理解了!(zip函数对我来说现在太高级了)再次感谢! - Terence Chow
在这里使用elifcontinue更好。 - georg
注意:这个答案同样适用于这个问题:http://codingbat.com/prob/p108886 - user5306470
@georg 你是什么意思? - user5306470

6
你可以使用 zip 函数来以对的方式循环值:
def special_sum(numbers):
    s = 0
    for (prev, current) in zip([None] + numbers[:-1], numbers):
        if prev != 13 and current != 13:
            s += current
    return s

或者您可以使用一行代码:
def special_sum(numbers):
    return sum(current for (prev, current) in zip([None] + numbers[:-1], numbers)
               if prev != 13 and current != 13)

您也可以使用迭代器:

from itertools import izip, chain
def special_sum(numbers):
    return sum(current for (prev, current) in izip(chain([None], numbers), numbers)
               if prev != 13 and current != 13)

(在izip中的第一个列表比第二个列表长,zipizip会忽略多余的值)。


哇,谢谢!这个看起来可以用,经过长时间的研究,我现在明白了。谢谢! - Terence Chow
这段代码非常浪费内存,并且不适用于迭代器 :) - Aleksei astynax Pirogov

3
使用while循环遍历列表,手动递增i。在每次迭代中,如果遇到13,则将i增加两次;否则,将值添加到累加和中并将i增加一次。
def skip13s(l):
    i = 0
    s = 0
    while (i < len(l)):
        if l[i] == 13:
            i += 1
        else:
            s += l[i]
        i += 1
    return s

2
一些函数式编程的例子 :)
def add_but_skip_13_and_next(acc, x):
    prev, sum_ = acc
    if prev != 13 and x != 13:
        sum_ += x
    return x, sum_

filter_and_sum = lambda l: reduce(add_but_skip_13_and_next, l, (0,0))[1]

>>> print filter_and_sum([13,13,1,4])
4
>>> print filter_and_sum([1,2,13,5,13,13,-9,13,13,13,13,13,1,1])
4

这段代码适用于任何迭代器,即使它不提供随机访问(直接索引)-例如套接字 :)
一行代码 :)
>>> filter_and_sum = lambda l: reduce(
...     lambda acc, x: (x, acc[1] + (x if x != 13 and acc[0] != 13 else 0)),
...     l, (0,0))[1]
>>> print filter_and_sum([1,2,13,5,13,13,-9,13,13,13,13,13,1,1])
4

1

我认为这是最紧凑的解决方案:

def triskaidekaphobicSum(sequence):
    return sum(sequence[i] for i in range(len(sequence))
               if sequence[i] != 13 and (i == 0 or sequence[i-1] != 13))

这里使用了内置的sum()函数和生成器表达式。生成器会产生序列中除了13或者紧随其后的元素之外的所有元素。额外的“or”条件是为了处理序列中的第一个元素(因为它没有前一个元素)。


0

你可以使用 while 循环来处理多个 13

def sum13(lis):
    while pos(lis):
        if pos(lis) == len(lis) - 1:
            lis = lis[:pos(lis)]
        else:
            lis = lis[:pos(lis)]+lis[pos(lis)+1:]

    return sum(lis)

由于某些原因,对于[13,1,2,13,2,1,13],这种方法不起作用...它给出了45作为总和。 - Terence Chow
我认为这是因为列表中的最新元素是13。所以我编辑了我的代码。 - plucury

0
def skipAndAddFun(inputVal, skipList):
   sum = 0
   for i in inputVal:
        if not i in skipList:
            sum += i
    return sum

使用方法:

skipAndAddFun([1,2,13,5,1], [13, 5])
4

这个简单的函数将是您问题的通用解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接