如何在OCaml / ReasonML中获取列表的一部分?

时间:2018-10-26 19:21:04

标签: ocaml reason

例如在Ruby中,您可以执行以下操作:

list = ["foo", "bar", "baz", "qux", "quux", "corge"]
result = list[2..4]

并且result将包含["baz", "qux", "quux"]

您将如何在OCaml / ReasonML中做到这一点?

5 个答案:

答案 0 :(得分:3)

切片列表没有内置的功能,但可以轻松完成。 由于我们有一个起点和一个终点,因此可以将问题分为两部分。第一部分是drop几个元素,直到到达起点为止;第二部分是take几个元素,从起点到终点。

let rec drop = (n, list) =>
  switch (list) {
  | [] => []
  | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
  };

let rec take = (n, list) =>
  switch (list) {
  | [] => []
  | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
  };

现在我们拥有这两个功能,我们可以将它们结合起来以删除初始元素,直到起点drop(i, list),然后传递此新列表以从起点到终点采用元素

take(k - i + 1, drop(i, list));
总共

let slice = (list, i, k) => {

  let rec drop = (n, list) =>
    switch (list) {
    | [] => []
    | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
    };

  let rec take = (n, list) =>
    switch (list) {
    | [] => []
    | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
    };

  take(k - i + 1, drop(i, list));
};

一种更好的方法是先提供起点,然后再提供范围,而不是终点,因为这里我们不限制终点应大于起点。

let slice = (list, start, range) => {

  let rec drop = (n, list) =>
    switch (list) {
    | [] => []
    | [_, ...xs] as z => n == 0 ? z : drop(n - 1, xs)
    };

  let rec take = (n, list) =>
    switch (list) {
    | [] => []
    | [x, ...xs] => n == 0 ? [] : [x, ...take(n - 1, xs)]
    };

  take(range, drop(start, list));
};

答案 1 :(得分:2)

如果您可以访问扣脚本的Belt库,则可以执行以下操作:

open Belt;

let myList = ["first", "second", "third", "fourth", "fifth", "sixth"];

/* To get 2..4 */
myList
  ->List.drop(2)
  ->Option.getWithDefault([])
  ->List.take(3)
  ->Option.getWithDefault([])
  ->Js.log;

/* Gives you the list ["third", "fourth", "fifth"] */

答案 2 :(得分:1)

使用

List.filteri (fun i _ -> i >= start && i <= end)

答案 3 :(得分:0)

OCaml切片没有特殊的语言符号。您可以编写函数,例如使用模式匹配,也可以将head与take函数结合使用(标准库中提供这些函数)。出于原因,将List.hd和List.tk https://reasonml.github.io/api/List.html结合起来,Array模块也有一个子列表Array.sub。 how to get a sub list from a list in ocaml

在此处讨论了OCaml

答案 4 :(得分:0)

如果您有权访问BuckleScript,则可以使用:

let list = ["foo", "bar", "baz", "qux", "quux", "corge"];

let sliced = Js.Array.slice(~start=2, ~end_=4, list);

BuckleScript docs

中查看更多