在列表末尾附加元素

the*_*ian 1 ocaml list reason

如何在ReasonML中的列表末尾追加一个元素(相当于Array.concatJavaScript)?

Nei*_*ner 9

您可以使用List.append@简写的操作员List.append.

let lstA = [ 1 ];
let lstB = lstA @ [ 2 ];
let lstC = List.append(lstB, [ 3 ]);
Run Code Online (Sandbox Code Playgroud)

以下是List方法的文档:https://reasonml.github.io/api/List.html

在这里查看游乐场链接:https://reasonml.github.io/en/try.html ?reason = DYUwLgBMDOYIIQLwQNoQIwQLoG4BQokMYAQklLAgAKoQBM2+hFYAwuQDICWsAdAIYAHQSAB2AEwAUxEgBpaAZmwBKfEA


gle*_*nsl 6

虽然Neil的答案在技术上是正确的,但它会掩盖您在达到之前可能要考虑的一些细节append; 特别是虽然在列表的开头添加元素非常便宜,但在末尾添加元素非常昂贵.

为了理解原因,让我们看看如何定义和构建列表.列表的(概念性)定义是:

type list('a) = Cons('a, list('a)) | Nil;
Run Code Online (Sandbox Code Playgroud)

where Nil表示列表的结尾(并且本身是一个空列表),Cons表示列表中的一个节点,包含一个类型的元素'a和一个指向列表其余部分的指针(list('a)).

如果我们拿走所有语法糖和每个辅助函数,你将不得不构造一个这样的列表:

let myList = Cons(1, Cons(2, Cons(3, Nil)));
Run Code Online (Sandbox Code Playgroud)

要在此列表的头部添加元素,我们构造一个包含新元素的节点和一个指向旧列表的指针:

let myBiggerList = Cons(0, myList);
Run Code Online (Sandbox Code Playgroud)

这和做的完全一样[0, ...myList].如果myList可以改变,我们当然不能做到这一点,但我们知道它不会,因为列表是不可变的.这使得这个非常便宜,并且出于同样的原因,它可以同样便宜地弹出头部,这就是为什么你通常会看到使用递归实现的列表处理函数,如下所示:

let rec map = f =>
  fun | []         => []
      | [x, ...xs] => [f(x), ...map(f, xs)];
Run Code Online (Sandbox Code Playgroud)

好的,那么为什么在列表的尾部添加元素这么昂贵呢?如果你回顾一下myList,在末尾添加一个元素意味着替换最后一个Nil,比如说Cons(4, Nil).但是我们需要更换,因为它指向Cons(3, ...)旧的Nil,Cons(2, ...)因为它指向旧的Cons(3, ...),依此类推整个列表.每次添加元素时都必须这样做.这很快就会增加.

那么你该怎么做呢?

如果你要添加到最后并且只是迭代它或者总是将元素放在最后,就像你经常在JavaScript中那样,你很可能只是颠倒你的逻辑.而不是添加和结束,添加和开始.

如果您确实需要FIFO数据结构,其中元素在一端插入并在另一端取下,请考虑使用队列.一般来说,看看这个标准容器的性能特征的比较.

或者,如果这一切都有点多,你真的只是喜欢这样做,就像你习惯使用JavaScript一样,只需使用一个array而不是一个list.您将在模块中找到您熟悉的所有功能Js.Array