Python 在列表中计算奇数
这是我家庭作业的一部分,我已经接近最后的答案了,但还不是很清楚。我需要写一个函数来计算列表中的奇数 创建一个递归函数count_odd(l),它的唯一参数是整数列表。该函数将返回奇数(即不能被2整除)列表元素数的计数\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 >>&
>>> 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))