从数组

时间:2015-10-22 05:42:27

标签: f#

我已经在这里待了几个小时,看着每个网站和文件我都可以。我无法弄清楚如何从一个数组中删除一个,只有一个元素(在本例中是一个字符串),保持任何重复。

确实找到了方法,但是,这绝对是残暴的:

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#中完整地做到这一点。

3 个答案:

答案 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|]