生成列表,直到使用单行满足某些条件

时间:2014-02-20 14:40:42

标签: python haskell generator list-comprehension

我一直在试图“进一步”改变我的内心,并偶然发现了这一点。如果我不禁止使用多行,只需使用一段时间即可。

所以我试图解决的示例问题如下(在其中一个编码站点上找到它:codercharts,codeeval等):

  

问题如下:选择一个数字,反转其数字并将其添加到原始数字。如果总和不是回文(这意味着它从左到右,从右到左不是相同的数字),重复此过程。

超级简单吧?一段时间就足够了,但我真的不知道如何在满足某个条件之前生成数字。我已经检查了itertools.takeWhileitertools.dropWhile,但这些都与现有列表一起使用,我仍然需要生成这些列表。

我尝试了生成器,但是我不知道如何在一行中压缩它们。

Argh,在Haskell中创建一个无限列表然后使用takeWhile会起作用,但在Python中我被卡住了。任何指向正确方向的指针都将非常感激。

编辑: 为了更简洁,我试图在一行上做这件事(当然是减去进口)。

1 个答案:

答案 0 :(得分:4)

我首先以递归的方式写这个:

def frob(x):
    if str(x) == str(x)[::-1]: 
        return x
    else:
        return frob(x + int(str(x)[::-1]))

print frob(29)

然后,由于lambda不能通过名称引用自身,我将删除显式递归并要求用户将该函数作为参数传递给自身。

def frob(f, x):
    if str(x) == str(x)[::-1]: 
        return x
    else:
        return f(f, x + int(str(x)[::-1]))

print frob(frob, 29)

这允许您将frob写为一行。

def frob(f, x):
    return x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1]))

print frob(frob, 29)

然后可以将其变成lambda函数。

frob = lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1]))

print frob(frob, 29)

您可以使用fixed point combinator修改函数的签名,以便它不再需要您明确地传递自己。

frob = (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))
print frob(29)

此时,您根本不再需要分配,并且可以在一行中调用lambda。

print (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))(29)

编辑:我刚刚注意到我误读了原来的问题陈述 - 有必要将该号码至少添加一次,即使它最初是一个回文。在这种情况下,我们仍然可以使用相同的函数,但是我们必须将它包装在执行第一步的内容中。

def troz(x):
    return frob(x + int(str(x)[::-1]))

减少到:

print (lambda x: (lambda f: lambda x: f(f,x))(lambda f, x: x if str(x) == str(x)[::-1] else f(f, x + int(str(x)[::-1])))(x + int(str(x)[::-1])))(29)