显示列表中项目的多次出现,sml

Show Multiple occurrences of items in a list, sml

我正在尝试显示列表中某个元素的所有多次出现的索引。

标准毫升

但我的代码显示空列表:(

这是我的代码:

    fun index(item, xs,ys) =
let
fun index'(m, nil , ys) = (
  SOME (ys) )
| index'(m, x::xr , ys) = if x = item then(
  (ys @ [m]);
  index'(m + 1, xr , ys)
  )
  else index'(m + 1, xr,ys)
in
index'(0, xs , ys)
end;


index(1,[1,2,1,4,5,1],[]);

你能帮帮我吗?

要事第一:

  1. index 应该有两个参数;要查找的元素和要查找的列表。
    累加参数属于辅助函数
  2. 总是生产SOME而从不生产NONE是没有意义的。

让我们先解决这些问题。

fun index (item, xs) =
    let
        fun index'(m, nil , ys) = ys
          | index'(m, x::xr, ys) = if x = item then(
                                       (ys @ [m]);
                                       index'(m + 1, xr , ys)
                                   )
                                   else index'(m + 1, xr,ys)
    in
        index'(0, xs, [])
end;

现在使用index时不需要传递额外的累加器参数了。
也不能从 [].

以外的其他内容开始

你的下一个主要问题是

(ys @ [m]);
index'(m + 1, xr , ys)

首先创建列表 ys @ [m],立即将其丢弃,然后生成结果 index'(m + 1, xr , ys),这正是 else 分支所做的。

即条件等价于

if x = item
then index'(m + 1, xr, ys)
else index'(m + 1, xr, ys)

因此,index' 等同于

fun index'(m, nil, ys) = ys
  | index'(m, x::xr, ys) = index'(m + 1, xr, ys)

由于您始终传递原始 ys,并且开始时是 [],因此结果始终是 []

你需要做的是将扩展列表传递给递归,这样它就可以成为递归终止时的结果。
重命名累加器 ys 以使其目的更清楚:

fun index (item, xs) =
    let
        fun index'(i, nil, accumulator) = accumulator
          | index'(i, x::xr, accumulator) = if x = item
                                            then index' (i + 1, xr, accumulator @ [i])
                                            else index' (i + 1, xr, accumulator)
    in
        index'(0, xs, [])
end;

这是低效的,因为要重复将一个元素追加到列表的后面。
逆向积累很常见,用完了再修正。
(这“感觉”效率低下,但事实并非如此。)

fun index (item, xs) =
    let
        fun index'(i, nil, accumulator) = List.reverse accumulator
          | index'(i, x::xr, accumulator) = if x = item
                                            then index' (i + 1, xr, i::accumulator)
                                            else index' (i + 1, xr, accumulator)
    in
        index'(0, xs, [])
end;