【发布时间】:2015-01-23 04:02:46
【问题描述】:
我正在解决一个涉及具有特定属性的所有 n 位数字的 Project Euler 问题。似乎获得它们的最简单方法可能是获取具有该属性的所有数字的列表(这将是无限长的),然后选择具有正确位数的数字。像这样:
numsWithCoolProperty = filter hasCoolProperty [1..]
nDigitNumsWithCoolProperty n = takeWhile (< 10^n) $ dropWhile (<= 10^(n-1)) numsWithOtherCoolProperty
但是现在如果我想对不同的属性做同样的事情,我会重复自己:
nDigitNumsWithOtherCoolProperty n = takeWhile (< 10^n) $ dropWhile (<= 10^(n-1)) numsWithOtherCoolProperty
所以我想要一个捕获 dropWhile/takeWhile 逻辑的函数。比如:
f :: (a -> Bool) -> [a] -> [a]
f pred = takeWhile pred . dropWhile (not . pred)
如果我有一个谓词 hasNDigits n m 如果 m 有 n 位返回 true,我可以这样做:
nDigitNumsWithCoolProperty n = f (hasNDigits n) numsWithCoolProperty
nDigitNumsWithOtherCoolProperty n = f (hasNDigits n) numsWithOtherCoolProperty
无论如何,我的问题是关于函数f,它与dropWhile 和takeWhile 具有相同的类型:它是否已经存在于某个地方?如果不是,它的好名字是什么?我能想到的只是dropUntilTakeWhile 之类的东西,但我敢肯定那里有更好的名字。
【问题讨论】:
-
您不需要使
take until + drop while递归吗?否则它只会在谓词匹配和非谓词匹配之间的单个转换上起作用。 (我完全不懂语法,所以我不知道你对f的定义是否已经这样做了) -
在这种特殊情况下,我知道
numsWithCoolProperty已排序(我想我应该这么说),这意味着我知道所有三位数字都将组合在一起。当它从两位数转换为三位数时,我想开始包括那些,当它从三位数转换为四位数时,我想停止。如果我不知道列表已排序(或者与谓词匹配的所有数字都在一次运行中分组),那么我将使用filter。但我不能在这里这样做,因为它是一个无限列表,我想得到一个有限的返回。 -
没什么帮助,但你可以称它为
takeRange,并将谓词称为isInRange -
另一种方法怎么样:
nDigitNums n = [10^(n-1)..10^n-1],然后对其进行过滤。 -
我会简单地调用该函数
dropTakeWhile。
标签: haskell functional-programming naming-conventions