List Haskell:列表边界

List Haskell:列表边界,list,haskell,limit,list-comprehension,predicate,List,Haskell,Limit,List Comprehension,Predicate,我有一个double列表(myList),我想将其添加到一个新列表(someList),但一旦新列表达到一个设定的大小,即25,我想停止添加到它。我曾尝试使用sum实现此函数,但未成功。下面的示例代码。 someList=[(a)| a 只要元素的总和小于25,就从myList中获取元素 逻辑发生在makeList中。它获取输入列表的第一个元素并将其添加到运行总数中,以查看其是否大于25。如果大于25,则不应将其添加到输出列表中,并完成递归。否则,我们将x放在输出列表的末尾(ys)然后继续输入列

我有一个double列表(myList),我想将其添加到一个新列表(someList),但一旦新列表达到一个设定的大小,即25,我想停止添加到它。我曾尝试使用sum实现此函数,但未成功。下面的示例代码。
someList=[(a)| a 只要元素的总和小于25,就从myList中获取元素


逻辑发生在
makeList
中。它获取输入列表的第一个元素并将其添加到运行总数中,以查看其是否大于25。如果大于25,则不应将其添加到输出列表中,并完成递归。否则,我们将
x
放在输出列表的末尾(
ys
)然后继续输入列表的其余部分。

您想要的行为是

ghci> appendWhileUnder 25 [1..5] [1..5]
[1,2,3,4,5,1,2,3]
因为这加起来是21,加上4等于25

好的,一种方法是在它们后面加上
++
,然后取25以下的初始段

appendWhileUnder n xs ys = takeWhileUnder n (xs++ys)
不想继续对中间列表求和,所以我将跟踪允许的数量(
n


它保留了整个
xs
,无论它是否会带你过来
n

丹尼尔菲舍对问题的表述方式与哈斯克尔的思维方式是一致的

是否希望someList是myList中总和小于30的最长前缀

下面是我的方法:假设我们的列表是

>>> let list = [1..20]
我们可以使用以下公式计算“累计金额”:

现在,将其与原始列表压缩,以获得到该点为止具有总和的元素对

>>> zip list (sums list)
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28),(8,36),
 (9,45),(10,55),(11,66),(12,78),(13,91),(14,105),(15,120),
 (16,136),(17,153),(18,171),(19,190),(20,210)]
然后我们可以
takeWhile
此列表以获得我们想要的前缀:

>>> takeWhile (\x -> snd x < 30) (zip list (sums list))
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28)]
>>takeWhile(\x->snd x<30)(邮政编码列表(金额列表))
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28)]
最后,我们可以去掉用于执行此计算的累积总和:

>>> map fst (takeWhile (\x -> snd x < 30) (zip list (sums list)))
[1,2,3,4,5,6,7]
>>映射fst(takeWhile(\x->snd x<30)(zip列表(总和列表)))
[1,2,3,4,5,6,7]
请注意,由于惰性,这与递归解决方案一样有效——只需计算测试失败点的总和。这一点可以看出,因为解决方案适用于无限列表(因为如果我们需要计算所有总和,我们将永远无法完成)

我可能会将其抽象出来,并将极限作为一个参数:

>>> :{
... let initial lim list =
...        map fst (takeWhile (\x -> snd x < lim) (zip list (sums list)))
... :}
>:{
…让初始lim列表=
…映射fst(takeWhile(\x->snd x
此函数有一个明显的属性,它应该满足,即列表的总和应始终小于限制(只要限制大于0)。因此,我们可以使用QuickCheck来确保我们做得正确:

>>> import Test.QuickCheck
>>> quickCheck (\lim list -> lim > 0 ==> sum (initial lim list) < lim)
+++ OK, passed 100 tests.
>导入Test.QuickCheck
>>>快速检查(\lim list->lim>0==>sum(初始lim list)
你能澄清列表的标准吗?你想让
someList
成为
myList
中最长的前缀,它有一个总和
<30
?谢谢你,这正是我需要的:)@user2180045-我对我的解决方案进行了一点重构,现在应该运行得更快了:)再次感谢,给我一点时间来理解你以前的建议解决方案:P汉克斯·安德鲁,暂时停止编写代码,尝试给出的所有答案。
>>> takeWhile (\x -> snd x < 30) (zip list (sums list))
[(1,1),(2,3),(3,6),(4,10),(5,15),(6,21),(7,28)]
>>> map fst (takeWhile (\x -> snd x < 30) (zip list (sums list)))
[1,2,3,4,5,6,7]
>>> :{
... let initial lim list =
...        map fst (takeWhile (\x -> snd x < lim) (zip list (sums list)))
... :}
>>> import Test.QuickCheck
>>> quickCheck (\lim list -> lim > 0 ==> sum (initial lim list) < lim)
+++ OK, passed 100 tests.