我已经在这里待了几个小时,看着每个网站和文件我都可以。我无法弄清楚如何从一个数组中删除一个,只有一个元素(在本例中是一个字符串),保持任何重复。
我确实找到了方法,但是,这绝对是残暴的:
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
我写了这个,我几乎不知道它是如何工作的。 请告诉我有更好的方法来做到这一点。我知道不需要变量变量,但我已经编写了十几个同样可怕的纯函数,并得出结论,这是我能做的最好的。我已经尝试了很多Array。*递归函数,我似乎无法使任何符合我想要的。我只是想知道是否甚至可以在F#中完整地做到这一点。
答案 0 :(得分:5)
我认为最简单的方法是首先查找索引(毕竟它是一个数组),然后将其删除 - 这是(我认为)性能和纯度之间的良好折衷 - 这是一个纯粹的操作但是你没有太多的复制操作:
static void evolve() {
char[][] temp = new char[m][n];
for (int r = 0; r < m; r++) {
for (int c = 0; c < n; c++) {
int neighbors = count_neighbors(r, c);
boolean occupied = grid[r][c] == 'X';
if (occupied && neighbors < 2) {
temp[r][c] = '.';
} else if (occupied && neighbors > 3) {
temp[r][c] = '.';
} else if (occupied && (neighbors == 2 || neighbors == 3)) {
temp[r][c] = 'X';
} else if (!occupied && neighbors == 3) {
temp[r][c] = 'X';
} else {
temp[r][c] = '.';
}
}
}
grid = temp.clone();
}
请注意,您必须处理第一个索引,因为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
将抛出异常(而另一个边缘情况正常):
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|]
答案 1 :(得分:0)
从列表中删除第一个项目(取自http://www.fssnip.net/1T):
let rec remove_first pred lst =
match lst with
| h::t when pred h -> t
| h::t -> h::remove_first pred t
| _ -> []
用法:
let somelist = [('a',2);('f',7);('a',4);('h',10)]
let removed = somelist |> remove_first (fun (x,y) -> x='a')
// Result is:
// [('f',7);('a',4);('h',10)]
答案 2 :(得分:0)
折叠应该可以解决问题:
let remove x a =
Array.fold
(fun (s,found) t ->
if found || t <> x then Array.append s [|t|],found
else s,true) ([||],false) a |> fst
使用示例:
remove 2 [|1; 2; 3; 4; 2; 5|]
val it : int [] = [|1; 3; 4; 2; 5|]