减少元组列表

时间:2014-05-13 13:51:07

标签: python tuples reduce

作为我学习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])

我的减少实施:

(bulls, cows) = reduce(\
    lambda (bull, cow), (b, c): \
        (bull + 1, cow + 1), bullsandcows(given, number), (0, 0))

其中given是用户输入,number是用户猜测的随机生成的数字。

正如您所看到的,这不是一个有效的实现,只会返回yield ed元组的计数。

我需要的是(bull + 1, cow + 1)的替代品,我不知道如何构建它。

  • number是一个随机生成的数字,例如:1234
  • 用户输入了
  • given,例如:8241
  • bullsandcows(given, number)的结果为:[('2', None), (None, '4'), (None, '1']
  • reduce的结果应为:(1, 2),这是第一个元素的所有非None值的计数和所有非None的计数第二个元素的值

1 个答案:

答案 0 :(得分: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))

仅当bullcow值不是None时,才会增加计数器。测试产生一个布尔值,它是int的子类False == 0True == 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)

e.g。使用zip()配对givennumber的数字。

演示:

>>> 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))