计算包含列表(SML)的列表的长度

时间:2016-06-01 18:00:33

标签: sml smlnj ml

SML长度函数:

fun length(L) =
    if (L=nil) then 0
    else 1+length(tl(L));

例如:

length [1,2,3] = 3;
length [ [5], [4], [3], [2,1] ] = 4;

根据代码,如果我还要计算列表列表中的元素,如何更改它?

例如:

length [ [5], [4], [3], [2,1] ] = 5;

3 个答案:

答案 0 :(得分:3)

您可以创建另一个将使用您的函数的函数,如下所示:

fun d_length ( [] ) = 0
| d_length ( l :: l' ) = length(l) + d_length(l');

d_length[ [5], [4], [3], [2,1] ];

或者,使用build in reducer:

List.foldl (fn(e,a) => length(e) + a) 0 [ [5], [4], [3], [2,1] ];

答案 1 :(得分:3)

您不希望进行比较L=nil,因为这仅适用于可比较类型的列表(例如,不是函数列表)。相反,你想要凯文约翰逊建议的模式匹配;

fun length [] = 0
  | length (x::xs) = 1 + length xs

或者使用尾递归:

fun length xs =
    let fun len [] n = n
          | len (x::xs) n = len xs (1+n)
    in len xs 0 end

length : 'a list -> int不同,此函数的类型为'a list list -> int

所有子列表的组合长度可以通过多种方式实现。 E.g。

fun length2 xss = List.foldl op+ 0 (List.concat xss)

但是,正如凯文的回答也充分利用了,当我们所做的就是稍后再次销毁它时,用List.concat xss构建一个新列表真的没有任何意义。所以无耻地撕掉他的解决方案:

fun length2 xss = List.foldl (fn (xs, sum) => length xs + sum) 0 xss

这也许是表达该函数最可读的方式,但是如果你试图使code golf函数真的很短,你也可以使用高阶函数重写内部闭包:

fun curry f x y = f (x, y)
fun uncurry f (x, y) = f x y
fun length2 xss = List.foldl (uncurry (curry op+ o length)) 0 xss

答案 2 :(得分:3)

这是一个模式匹配的直接递归版本,它不使用内置的length函数,而是直接计算总长度(“tol”):

fun tol [] = 0
|   tol ([]::xss) = tol xss
|   tol ((x::xs)::xss) = 1 + tol (xs::xss);

最后一句中的括号顺序很重要。它会覆盖::的右关联性,以便将x中的(x::xs)::xss解释为xss中第一个列表的头部而不是xss的头部本身。

这些答案的模式似乎是以折叠结束,我不想打破模式。这是一个折叠,折叠为通过在列表列表上映射长度获得的列表的总和:

fun tol xss = foldl op+ 0 (map length xss);