最基本的方法是遍历列表,在递归处理其余部分后,将当前元素附加到三个返回的列表之一。您需要向函数添加一个额外的参数 i
来跟踪列表中的位置(然后使用它来确定当前元素应该放在哪里)。最基本形式的一般结构如下:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] ->
// Empty list just becomes a triple of empty lists
[], [], []
| x::xs ->
// Process the rest of the list recursively. This
// gives us three lists containing the values from 'xs'
let l1, l2, l3 = loop (i + 1) xs
// Now comes the tricky bit. Here you need to figure out
// whether 'x' should go into 'l1', 'l2' or 'l3'.
// Then you can append it to one of them using something like:
l1, x::l2, l3
// Walk over the list, starting with index 'i=0'
loop 0 l
如何处理棘手的问题?我没有一个完全符合您要求的解决方案,但以下方法类似 - 它只是查看变量i
是否大于长度的三分之一或者二分之一:
let split l =
let length = List.length l
let rec loop i l =
match l with
| [] -> [], [], []
| x::xs ->
let l1, l2, l3 = loop (i + 1) xs
if i >= length / 3 * 2 then l1, l2, x::l3
elif i >= length / 3 then l1, x::l2, l3
else x::l1, l2, l3
loop 0 l
这将始终创建长度为
length / 3
的组,并将剩余的元素放在最后一个列表中。
split [1..3] // [1], [2], [3]
split [1..4] // [1], [2], [3
split [1..5] // [1], [2], [3
split [1..6] // [1
您应该能够将其调整为您需要的行为-需要进行一些棘手的计算,以精确确定切换点的位置,但这只是确保+/-1正确的问题!
[1, 2, 3]
是一个包含单个元素的列表,该元素是一个三元组。[1,2,3,4,5,6,7]
是一个包含单个元素的列表,该元素是一个七元组。同样,l1
、l2
和l3
都是仅包含单个元素的列表,这些元素是各种元组。匹配返回列表的元组。我怀疑您将分号的使用与冒号的使用混淆了。我不确定您是否理解元组的含义。具有不同元数的元组不兼容。 - Bent TranbergList.splitInto
功能相同的函数,那么元组根本不需要参与,现在先忘记它们。你需要将所有逗号替换为分号,这样你就可以得到你想要的实际列表元素,然后从那里开始处理。 - Bent Tranberg