You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为多个数字生成有序倍数列表?Haskell作业求助

解决Haskell中合并多个整数倍数有序列表的问题

嘿,我明白你现在遇到的问题了——你已经搞定了单个整数的无限倍数列表,现在要扩展成处理多个因子,并且输出有序且无重复的倍数列表对吧?你之前用的列表推导式之所以输出无序的结果,是因为它先把每个y对应的所有因子的倍数都列出来了(比如y=1时先出3、5,y=2时出6、10),而不是按全局大小排序。

下面给你两种可行的方案,其中第一种就用到了你提到的取模函数提示:

方案一:筛选法(利用取模判断整除)

这个思路很直接:生成所有正整数,然后筛选出能被列表中任意一个因子整除的数。代码实现如下:

function :: [Int] -> [Int]
function ds = [n | n <- [1..], any (\d -> n `mod` d == 0) ds]

解释:

  • n <- [1..] 生成无限的正整数序列
  • any (\d -> n mod d == 0) ds 检查当前n是否能被ds中的至少一个因子整除:n mod d == 0 就是判断n是d的倍数的核心条件,any函数只要有一个d满足条件就返回True
  • 测试一下:take 10 (function [3,5]) 会返回 [3,5,6,9,10,12,15,18,20,21],完全符合你的需求!

这种方法的优点是简单直观,容易理解;缺点是如果因子列表ds很大,或者因子本身很大,效率会稍低,因为每个n都要遍历所有因子检查整除性。

方案二:合并有序子列表(更高效的方式)

既然每个单个因子的倍数列表都是有序的(比如function 3是[3,6,9,...],function 5是[5,10,15,...]),我们可以把这些有序列表合并成一个全局有序且无重复的列表。

首先实现两个有序列表的合并函数(带去重):

merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
  | x < y     = x : merge xs (y:ys)
  | x > y     = y : merge (x:xs) ys
  | otherwise = x : merge xs ys  -- 遇到重复元素只保留一个

然后实现合并多个有序列表的函数:

mergeAll :: Ord a => [[a]] -> [a]
mergeAll [] = []
mergeAll (x:xs) = merge x (mergeAll xs)

最后,你的目标函数可以写成:

function :: [Int] -> [Int]
function ds = mergeAll [map (*d) [1..] | d <- ds]

解释:

  • [map (*d) [1..] | d <- ds] 先生成每个因子对应的无限倍数列表
  • mergeAll 把这些有序列表逐步合并成一个全局有序的列表,同时自动去重
  • 测试同样会得到正确的结果,而且这种方法的效率更高,因为它利用了子列表有序的特性,不需要逐个检查每个数。

为什么你之前的列表推导式不行?

你写的 [y*x | y <- [1..], x <- d] 是先遍历y的每个值,再遍历d中的每个因子,所以生成的顺序是:
y=1时:31,51 → [3,5]
y=2时:32,52 → [6,10]
y=3时:33,53 → [9,15]
...
这样拼接起来的列表自然是[3,5,6,10,9,15,...],不是全局有序的,这就是问题所在。

内容的提问来源于stack exchange,提问作者csstudent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:38:25