Python 在列表中计算奇数

Python 在列表中计算奇数,python,recursion,Python,Recursion,这是我家庭作业的一部分,我已经接近最后的答案了,但还不是很清楚。我需要写一个函数来计算列表中的奇数 创建一个递归函数count_odd(l),它的唯一参数是整数列表。该函数将返回奇数(即不能被2整除)列表元素数的计数\ >>> print count_odd([]) 0 >>> print count_odd([1, 3, 5]) 3 >>> print count_odd([2, 4, 6]) 0 >>&

这是我家庭作业的一部分,我已经接近最后的答案了,但还不是很清楚。我需要写一个函数来计算列表中的奇数

创建一个递归函数count_odd(l),它的唯一参数是整数列表。该函数将返回奇数(即不能被2整除)列表元素数的计数\

>>> print count_odd([])  
0  
>>> print count_odd([1, 3, 5])  
3  
>>> print count_odd([2, 4, 6])  
0  
>>> print count_odd([0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144])  
8  
以下是我到目前为止的情况: #-递归函数计数奇数-#

def count_奇数(l):
“”“返回l中奇数整数的计数。
PRE:l是一个整数列表。
职位:l不变
计数奇数=0

当count_odd时,递归的目标是将问题分成更小的部分,并将解决方案应用于更小的部分。在这种情况下,我们可以检查列表的第一个数(<代码> L(0)< /代码>)是否为奇数,然后再次调用该函数(这是“递归”)与列表的其余部分(<代码> L[ 1:] /代码>,将当前结果添加到递归结果中。

< P>因为这是家庭作业,请考虑这个仅列出列表的伪代码:

function count (LIST)
    if LIST has more items
        // recursive case.
        // Add one for the current item we are counting,
        // and call count() again to process the *remaining* items.
        remaining = everything in LIST except the first item
        return 1 + count(remaining)
    else
        // base case -- what "ends" the recursion
        // If an item is removed each time, the list will eventually be empty.
        return 0
这与家庭作业的要求非常相似,但需要将其转换为Python,并且必须制定正确的递归案例逻辑

快乐的编码。

切片可以吗?我觉得不是递归的,但我想整个过程有点违背了通常的习惯用法(即Python中的这种递归):

x%2
1
的赔率,是
0的赔率。如果您对它感到不舒服或只是不理解它,请使用以下内容代替上面的最后一行:

   thisElement = l[0]
   restOfList = l[1:]
   if thisElement % 2 == 0: currentElementOdd = 0
   else: currentElementOdd = 1
   return currentElementOdd + countOdd(restOfList)
PS-这是非常递归的,如果你把它交给=p,看看你的老师怎么说

>>> def countOdd(l):
...     return fold(lambda x,y: x+(y&1),l,0)
... 
>>> def fold(f,l,a):
...     if l == list(): return a
...     return fold(f,l[1:],f(a,l[0]))
尾部递归 Python中没有尾部调用优化,因此上面的版本纯粹是教育性的

该调用可以可视化为:

count_odd([1,2,3])    # returns
iter_([1,2,3], 0)      # could be replaced by; depth=1
iter_([2,3], 0 + is_odd(1)) if [1,2,3] else 0 # `bool([1,2,3])` is True in Python
iter_([2,3], 0 + True) # `True == 1` in Python
iter_([2,3], 1)        # depth=2
iter_([3], 1 + is_odd(2)) if [2,3] else 1
iter_([3], 1 + False)  # `False == 0` in Python
iter_([3], 1)          # depth=3
iter_([], 1 + is_odd(3)) if [3] else 1
iter_([], 2)           # depth=4
iter_(rest([]), 2 + is_odd(first([])) if [] else 2 # bool([]) is False in Python
2 # the answer
简易蹦床 为了避免大型数组出现“超过最大递归深度”错误,可以将递归函数中的所有尾部调用包装在
lambda:
表达式中;可以使用特殊的
trampoline()
函数来展开这些表达式。它有效地将递归转换为在简单循环上迭代:

import functools

def trampoline(function):
    """Resolve delayed calls."""
    @functools.wraps(function)
    def wrapper(*args):
        f = function(*args)
        while callable(f):
            f = f()
        return f
    return wrapper

def iter_(lst, count):
    #NOTE: added `lambda:` before the tail call
    return (lambda:iter_(rest(lst), count+is_odd(first(lst)))) if lst else count

@trampoline
def count_odd(integers):
    return iter_(integers, 0)
例如:

count_odd([1,2,3])
iter_([1,2,3], 0)         # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([2,3], 0+is_odd(1)) # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([3], 1+is_odd(2))   # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([], 1+is_odd(3))
2                         # callable(2) is False

我会这样写:

def countOddNumbers(numbers): 
    sum = 0
    for num in numbers:
        if num%2!=0:
            sum += numbers.count(num)
    return sum 

所有先前的答案都是将问题细分为大小为1和大小为n-1的子问题。一些人注意到递归堆栈可能很容易崩溃。此解决方案应将递归堆栈大小保持在O(logn):

def count_奇数(系列):
l=len(系列)>>1
如果l<1:
如果序列为0,则返回序列[0]&1
其他:
返回计数奇数(系列[:l])+计数奇数(系列[l:])

我不确定是否收到了您的问题,但如上所述:

def countOddNumbers(numbers): 
    count=0
    for i in numbers:
        if i%2!=0:
            count+=1
    return count

生成器可以在一行代码中快速生成结果:

sum((x%2 for x in nums))

你错过了递归。你能解释一下我怎么做递归吗?我是python新手,而我们的教授对递归的解释并没有那么好。不是特定于Python的概念。一般来说,当函数体作为计算的一部分调用函数本身时,您正在执行递归。请阅读以下内容:。然后再试一次。而且,即使这个函数中没有递归,逻辑也是有缺陷的。试着用
[2,4,6]
参数一次一行地检查它,看看你是否能发现故障。嗯,好的,把它分成更小的部分是有意义的。现在我要试着把它融入我的代码中!这确实是解决问题的全功能方法。不是说我会用Python来做这件事,但是因为老师要求递归…@justin不应该有“while”和“counter”变量——计数是通过添加一些东西来完成的(在上面的例子中是“1”,但你可能需要使它依赖于一些东西)对于下一个递归调用的返回值:-),您可以对列表执行的唯一操作是“告诉是否还有更多项”(
len(list)
),“第一次查看”(
list[0]
——如果有),以及“获取列表的其余部分”(
list[1:
——除第一项以外的所有内容)。对于此问题,对于n!=0(例如,您不能对列表进行索引迭代)。hmmm确定返回到绘图board@justin如果您得到了我发布的使用Python的计数版本(因此,对于每个列表l,
count(l)=len(l)
),则只需调整它,使其仅在当前项的特定条件为真时计数。快乐编码。嗯,好的。我会尽力的。我是python的初学者,所以可能需要一些时间。学习一门新的编程语言非常令人沮丧。
如果l==list():
应该被
如果不是l:
取代。可以提到内置的
reduce()
函数(在您的代码中它被命名为
fold()
)。实际上,整个过程只是一行:
count\u odd=lambda l:l[0]%2+count\u odd(l[1:]),如果l为0
。这就是我所说的递归@martineau:@Satoru.Logic已经提供了变体@J.F.Sebastian:相同的逻辑,但有两行。我很清楚reduce,但如果我使用它,它看起来不会太递归,是吗?我选择了“fold”这个名称,这样我就不会重新定义reduce,因为我不想覆盖双参数形式。该函数可以用尾部递归方式编写,例如,基于
fold
的解决方案尾部调用优化可以应用于此类程序,例如。,通过蹦床,Python中的递归限制很小,因此即使对于平均大小的数组,非优化解决方案也不起作用:
count\u odd([1]*1001)
。虽然它是尾部递归形式,但我已经测试了我的“折叠”,没有TCO。不足为奇——即使是它的尾部递归,我知道python也不支持这一点。问题是,native reduce是如何解决这个问题的?@jon_darkstar:TCO可以通过简单的蹦床引入的,是的,我得到了这么多。他们用内置的reduce做什么?@jon_darkstar:
reduce()
对我们来说不是吗
import functools

def trampoline(function):
    """Resolve delayed calls."""
    @functools.wraps(function)
    def wrapper(*args):
        f = function(*args)
        while callable(f):
            f = f()
        return f
    return wrapper

def iter_(lst, count):
    #NOTE: added `lambda:` before the tail call
    return (lambda:iter_(rest(lst), count+is_odd(first(lst)))) if lst else count

@trampoline
def count_odd(integers):
    return iter_(integers, 0)
count_odd([1,2,3])
iter_([1,2,3], 0)         # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([2,3], 0+is_odd(1)) # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([3], 1+is_odd(2))   # returns callable
lambda:iter_(rest(lst), count+is_odd(first(lst))) # f = f()
iter_([], 1+is_odd(3))
2                         # callable(2) is False
def countOddNumbers(numbers): 
    sum = 0
    for num in numbers:
        if num%2!=0:
            sum += numbers.count(num)
    return sum 
def count_odd(series):
    l = len(series) >> 1
    if l < 1:
        return series[0] & 1 if series else 0
    else:
        return count_odd(series[:l]) + count_odd(series[l:])
def countOddNumbers(numbers): 
    count=0
    for i in numbers:
        if i%2!=0:
            count+=1
    return count
sum((x%2 for x in nums))