减少元组列表
在我学习Python的过程中,我正在实现一个“牛和水”的游戏。
我已经有了一个可以工作的版本,使用了列表推导式,但我想试试用生成器来解决这个问题,并用reduce()
来得到最终结果。
这是我的生成器:
def bullsandcows(given, number):
for i in range(given.__len__()):
if given[i] == number[i]:
yield (given[i], None)
elif given[i] in number:
yield (None, given[i])
这是我的reduce实现:
(bulls, cows) = reduce(\
lambda (bull, cow), (b, c): \
(bull + 1, cow + 1), bullsandcows(given, number), (0, 0))
在这里,given
是用户输入的数字,而number
是随机生成的数字,用户需要猜这个数字。
如你所见,这个实现并不是完全可用的,它只是返回了yield
生成的元组的计数。
我需要的是替换(bull + 1, cow + 1)
的部分,但我不知道该怎么构造这个。
number
是一个随机生成的数字,比如说:1234
given
是用户输入的数字,比如说:8241
- 调用
bullsandcows(given, number)
的结果应该是:[('2', None), (None, '4'), (None, '1')]
- 而
reduce
的结果应该是:(1, 2)
,这表示第一个元素中所有非None
值的数量和第二个元素中所有非None
值的数量
1 个回答
2
如果我理解得没错,你想要统计哪些 bull
不是 None
,还有多少 cow
不是 None
:
reduce(lambda (bcount, ccount), (b, c): (bcount + (b is not None), ccount + (c is not None)),
bullsandcows(given, number), (0, 0))
这个代码的作用是只有在 bull
或 cow
的值不是 None
的时候,才会增加一个计数器。测试的结果是一个布尔值,布尔值是整数的一种特殊类型,其中 False
等于 0,而 True
等于 1;把一个整数和一个布尔值相加,结果会是另一个整数。
因为你输入的是非空字符串,所以你可以把它简化为:
reduce(lambda (bcount, ccount), (b, c): (bcount + bool(b), ccount + bool(c)),
bullsandcows(given, number), (0, 0))
我会把 bullsandcows()
改写成:
def bullsandcows(given, number):
given, number = map(str, (given, number))
for g, n in zip(given, number):
if g == n:
yield (g, None)
elif g in number:
yield (None, g)
比如说,使用 zip()
函数来把 given
和 number
的数字配对起来。
示例:
>>> def bullsandcows(given, number):
... given, number = map(str, (given, number))
... for g, n in zip(given, number):
... if g == n:
... yield (g, None)
... elif g in number:
... yield (None, g)
...
>>> given, number = 8241, 1234
>>> list(bullsandcows(given, number))
[('2', None), (None, '4'), (None, '1')]
>>> reduce(lambda (bcount, ccount), (b, c): (bcount + bool(b), ccount + bool(c)),
... bullsandcows(given, number), (0, 0))
(1, 2)
注意,在函数参数中解包的功能在 Python 3 中被移除了,而 reduce()
这个内置函数也被转移到了库函数中;所以你的代码只能在 Python 2 中运行。
要让它在 Python 3 中工作,你需要导入 functools.reduce()
,并调整 lambda 表达式,使其不使用解包:
from functools import reduce
reduce(lambda counts, bc: (counts[0] + bool(bc[0]), counts[1] + bool(bc[1])),
bullsandcows(given, number), (0, 0))