我想要一个List或Array,并在集合中给出两个元素,获取它们之间的所有元素。但我希望以循环的方式做到这一点,例如给定一个列表[1;2;3;4;5;6]
,如果我要求介于4和2之间的元素,我会回来[5;6;1]
习惯于命令式编程我可以很容易地用循环来做这件事,但我想在F#中可能有一个更好的习惯方法。
修改
这是我提出的一种方法,找到了Array.indexed函数
let elementsBetween (first:int) (second:int) (elements: array<'T>) =
let diff = second - first
elements
|> Array.indexed
|> Array.filter (fun (index,element) -> if diff = 0 then false
else if diff > 0 then index > first && index < second
else if diff < 0 then index > first || index < second
else false
这种方法只适用于数组,但这似乎相当不错。我有一种感觉,我可以通过用模式匹配替换if / then / else来清理它,但我不确定如何干净地做到这一点。
答案 0 :(得分:2)
我没有使用f#编译器在我的普通计算机上,所以我还没有测试过它。它应该看起来像这样
[编辑]感谢@FoggyFinder向我展示https://dotnetfiddle.net/。我现在用它来测试下面的代码。
[编辑]这应该在一次通过中找到圆形范围。
let x = [1;2;3;4;5]
let findCircRange l first second =
let rec findUpTo (l':int list) f (s:int) : (int list * int list) =
match l' with
| i::tail ->
if i = s then tail, (f [])
else findUpTo tail (fun acc -> f (i::acc)) s
// In case we are passed an empty list.
| _ -> [], (f [])
let remainder, upToStart = findUpTo l id first
// concatenate the list after start with the list before start.
let newBuffer = remainder@upToStart
snd <| findUpTo newBuffer id second
let values = findCircRange x 4 2
printf "%A" values
findUpTo获取一个列表(l&#39;),一个用于创建余数列表(f)的函数和一个要查找的值。我们通过它递归(尾递归)来找到给定值的列表和给定值之后的列表。通过将结尾附加到剩余部分来包裹缓冲区。再次将它传递给findUpTo以找到最后。将缓冲区返回到最后。
我们传递一个累积找到的项目的函数。这种技术允许我们在函数调用unwind时附加到列表的末尾。
当然,这里没有错误检查。我们假设开始和结束确实存在。这将留给读者练习。
答案 1 :(得分:2)
您应该查看MSDN,Collections.Seq模块。
让我们试着变得聪明:
let elementsBetween a e1 e2 =
let aa = a |> Seq.append a
let i1 = aa |> Seq.findIndex (fun e -> e = e1)
let i2 = aa |> Seq.skip i1 |> Seq.findIndex (fun e -> e = e2)
aa |> Seq.skip(i1+1) |> Seq.take(i2-1)
答案 2 :(得分:0)
这是使用你的diff与列表和列表切片的想法的变体
<some list.[x .. y]
let between (first : int) (second : int) (l : 'a list) : 'a list =
if first < 0 then
failwith "first cannot be less than zero"
if second < 0 then
failwith "second cannot be less than zero"
if first > (l.Length * 2) then
failwith "first cannot be greater than length of list times 2"
if second > (l.Length * 2) then
failwith "second cannot be greater than length of list times 2"
let diff = second - first
match diff with
| 0 -> []
| _ when diff > 0 && (abs diff) < l.Length -> l.[(first + 1) .. (second - 1)]
| _ when diff > 0 -> (l@l).[(first + 1) .. (second - 1)]
| _ when diff < 0 && (abs diff) < l.Length -> l.[(second + 1) .. (second + first - 1)]
| _ when diff < 0 -> (l@l).[(second + 1) .. (second + first - 1)]