我现在已经在这几个小时了,看看我能做的每个网站和文档.我无法弄清楚如何从一个数组中删除一个,只有一个元素(在这种情况下,一个字符串),保持任何重复.
我确实找到了办法,但是,这绝对是残暴的:
let remItem gs item =
if (chkItem gs item) then
let mutable fr = [| |] //temporary array
let mutable don = false //check if we found the element
for i in gs.inventory do
if not (i = item) && don then
fr <- (Array.append fr [|i|])
//add to the temp array until we find our item
elif i = item && don = false then don <- true
//we found it, skip just once so it doesn't get added
elif don then fr <- (Array.append fr [|i|])
//now just add everything else to the temp array
{ gs with inventory = fr }
else gs
Run Code Online (Sandbox Code Playgroud)
我写了这个,我几乎不知道它是如何工作的.请告诉我有更好的方法来做到这一点.我知道不需要变量变量,但我写了十几个同样可怕的纯函数,并得出结论,这是我能做的最好的.我已经尝试了很多Array.*递归函数,我似乎无法使任何符合我想要的.我只是想知道是否甚至可以在F#中完整而纯粹地做到这一点.
我认为最简单的方法是首先查找索引(毕竟它是一个数组),然后将其删除 - 这是(我认为)性能和纯度之间的良好折衷 - 这是一个纯粹的操作,但你不要没有太多的复制操作:
let remove x (xs : 'a array) =
match Array.tryFindIndex ((=) x) xs with
| Some 0 -> xs.[1..]
| Some i -> Array.append xs.[..i-1] xs.[i+1..]
| None -> xs
Run Code Online (Sandbox Code Playgroud)
请注意,你必须在第一个索引处理它,因为xs.[..(-1)]会抛出一个异常(而另一个边缘情况是好的):
> remove 0 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
> remove 1 [|1..10|];;
val it : int [] = [|2; 3; 4; 5; 6; 7; 8; 9; 10|]
> remove 3 [|1..10|];;
val it : int [] = [|1; 2; 4; 5; 6; 7; 8; 9; 10|]
> remove 9 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 10|]
> remove 10 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9|]
> remove 11 [|1..10|];;
val it : int [] = [|1; 2; 3; 4; 5; 6; 7; 8; 9; 10|]
Run Code Online (Sandbox Code Playgroud)
如果你需要更多的性能,你可以创建一个空数组并使用更强制的样式来复制部件:
let remove x (xs : 'a array) =
match Array.tryFindIndex ((=) x) xs with
| Some i ->
let res = Array.zeroCreate (xs.Length-1)
if i >= 1 then
System.Array.Copy(xs,0,res,0,i)
if i+1 < xs.Length then
System.Array.Copy(xs,i+1,res,i,xs.Length-i-1)
res
| None -> xs
Run Code Online (Sandbox Code Playgroud)