例如,在 Ruby 中,您可以执行以下操作:
list = ["foo", "bar", "baz", "qux", "quux", "corge"]
result = list[2..4]
Run Code Online (Sandbox Code Playgroud)
而result将包含["baz", "qux", "quux"]。
你会如何在 OCaml/ReasonML 中做到这一点?
没有用于切片列表的内置功能,但可以轻松完成。由于我们有起点和终点,我们可以将问题分解为两部分。第一部分是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)]
};
Run Code Online (Sandbox Code Playgroud)
现在我们有了这两个函数,我们可以将它们组合起来,从起点到起点删除初始元素drop(i, list),然后传递这个新列表以从起点到终点获取元素
take(k - i + 1, drop(i, list));
Run Code Online (Sandbox Code Playgroud)
总共
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));
};
Run Code Online (Sandbox Code Playgroud)
更好的方法是提供起点,然后提供范围而不是终点,因为在这里我们不限制终点应该大于起点
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));
};
Run Code Online (Sandbox Code Playgroud)