例如在Ruby中,您可以执行以下操作:
list = ["foo", "bar", "baz", "qux", "quux", "corge"]
result = list[2..4]
并且result
将包含["baz", "qux", "quux"]
。
您将如何在OCaml / ReasonML中做到这一点?
答案 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);
中查看更多