当前位置: 首页 > 知识库问答 >
问题:

构建无限列表的排序无限列表

东方琪
2023-03-14

我知道对无限列表进行排序是不可能的,但我正试图为n个数的倍数的无限递增列表写一个定义。

我已经有这个功能了

multiples :: Integer -> [Integer]
multiples n = map (*n) [1..]

它返回n的无限倍数列表。但现在我想构建一个函数,给定一个整数列表返回列表中所有数字的倍数的无限递增列表。所以函数multiplesList::[Integer]-

我是Haskell的新手,我正在努力解决这个问题。我想我应该使用foldrmap,因为我必须对输入中的所有数字应用倍数,但是我不知道怎么做。我不能把所有列表混合成一个。

如果有人能帮我,我将不胜感激。

非常感谢。


共有2个答案

司徒兴思
2023-03-14

我们可以很容易地将两个无限列表按位置编织在一起,每一步从每个列表中提取一个元素,

weave (x:xs) ys = x : weave ys xs

或者我们可以每次使用更长的前缀,

-- warning: expository code only
weaveN n xs ys = take n xs ++ weaveN n ys (drop n xs)

但假设两个列表不仅是无限的,而且是严格递增的(即列表中没有重复项),我们可以通过相反列表的头值来引导前缀的选取:

umerge :: Ord a => [a] -> [a] -> [a]
-- warning: only works with infinite lists
umerge xs (y:ys) = a ++ [y | head b > y ] ++ umerge ys b
  where
    (a,b) = span (< y) xs

因此,这是唯一合并操作的一种可能编码(“唯一”意思是,其输出中不会有任何重复项)。

在测试中,它似乎按预期工作:

> take 20 $ umerge [3,6..] [5,10..]
[3,5,6,9,10,12,15,18,20,21,24,25,27,30,33,35,36,39,40,42]

> [3,6..42] ++ [5,10..42] & sort & nub
[3,5,6,9,10,12,15,18,20,21,24,25,27,30,33,35,36,39,40,42]

> [ p | let { ms :: [Integer] ; ms = takeWhile (< 25^2) $
          foldl1 umerge [[p*p,p*p+p..] | p <- [2..25]] },
    p <- [2..545],  not $ elem p ms ]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,
 97,101,...........,499,503,509,521,523,541]

> length it
100

通过一个巧妙的小调整(由于理查德·伯德在梅利莎·奥尼尔的JFP文章中看到),它甚至可以用来折叠一个无限的升序列表,前提是它是按照头部元素的升序排序的,所以第一个参数的头部保证是输出中的第一个,因此可以在没有测试的情况下生成:

umerge1 :: Ord a => [a] -> [a] -> [a]
-- warning: only works with infinite lists
--          assumes x < y
umerge1 (x:xs) ~(y:ys) = x : a ++ [y | head b > y ] ++ umerge ys b
  where
    (a,b) = span (< y) xs

现在

> take 100 [ p | let { ms :: [Integer] ;
          ms = foldr1 umerge1 [[p*p,p*p+p..] | p <- [2..]] },
    p <- [2..],  not $ elem p $ takeWhile (<= p) ms ]

[2,3,5,7,11,13, ...... 523,541]

同样的计算无限期地起作用。

对观众中的文字主义者来说:是的,在这里叫elem是非常糟糕的事情。希望操作人员自己也能认识到这一点,但不幸的是,我觉得有必要发表这一声明,从而无意中向他们透露了这一点,不幸的是,剥夺了他们本应获得的哈哈时刻。

此外,umerge1的定义可以大大简化。同样,这是留给OP自己去发现的。(同样,如果我不是被迫说这句话来向他们揭示这一点的话,对他们来说,这会好得多——自己去寻找一些东西会更有力量和满足感)

(*),并自行寻找更有效的方法来取代它。不,这段代码并不是解决他们问题的最佳方案

井轶
2023-03-14

你走在正确的道路上。下面的评论是一个你可以完成的模板。


multiples :: Integer -> [Integer]
multiples n = map (*n) [1..]

-- This is plain old gold recursion.
mergeSortedList :: [Integer] -> [Integer] -> [Integer]
mergeSortedList [] xs = undefined
mergeSortedList xs [] = undefined
mergeSortedList (x:xs) (y:ys)
    | x < y  = x:mergeSortedList xs (y:ys) -- Just a hint ;)
    | x == y = undefined
    | x > y  = undefined

multiplesList :: [Integer] -> [Integer]
multiplesList ms = undefined -- Hint: foldX mergeSortedList initial xs
                             -- Which are initial and xs?
                             -- should you foldr or foldl?


 类似资料:
  • 问题内容: 是否有人在Redis中实现了任何形式的有上限的数据结构?我正在构建类似新闻提要的东西。提要将非常频繁地被操纵和读取,并且将其保存在Redis的分类集中对于我的用例来说是便宜又完美的。唯一的问题是,每个提要仅需要n个项,并且我担心内存溢出,因此我想确保每个提要都不会超过n个项。用Lua在Redis中创建一个有上限的排序集合似乎很简单: update_feed.lua看起来像(未经测试):

  • 我试图在Haskell中编写一个函数,它可以做以下操作:输入一个整数列表,对于这些整数,使用map,有一个函数应用于它们,返回一个无限的整数列表。然后,我想使用union将foldr应用于列表,这样结果将是列表中这些列表的union。 现在的问题是,当我以10‘函数’[1,2]为例进行计算时,它会首先计算1的无限列表,因为它是一个无限列表,它永远不会对2进行计算。因此,它只返回输入列表中第一个元素

  • 问题内容: 我需要居中排列一个宽度未知的无序列表,同时仍然保持列表项对齐。 获得与以下相同的结果: HTML CSS 除了我没有父母div。无法使用,因为我没有固定的宽度。不起作用,因为列表项将不再保持对齐。那么,如何在保持s对齐的同时居中(没有父div包装器)呢? 编辑 :也许我的措辞是不是最好的…第一个代码块已经工作…我需要的是做 不 的包装,如果这当然是可能的。浮动花样?伪元素技巧?一定有办

  • 问题内容: 我有以下情况: Python 3.6+ 从文件中逐行读取输入数据。 协程将数据发送到API(使用),并将调用结果保存到Mongo(使用)。因此,有很多IO正在进行。 该代码使用/编写,并且对于手动执行的单个调用也可以正常工作。 我不知道该怎么做,就是要大量使用输入数据。 我看到的所有示例都通过发送有限列表作为参数进行了演示。但是我不能简单地向它发送任务列表,因为输入文件可能有数百万行。

  • 我想有一个arrayList记录用户条目,并在收到非整数值时结束,但我有一个无限循环idk why。

  • 做这件事的正确方法是什么?