我有三个阵列 - 第一,第二和第三。第二个包含第一个和第三个的唯一值包含新的替换值,首先映射到第二个,如下所示:
module SOQN =
open System
let first = [|"A"; "B"; "C"; "A"; "B"; "A"; "C"; "B"; "C"; "C"; "C"|]
let second = [|"A"; "B"; "C"|]
let third = [|"1"; "2"; "3"|]
let rplc (x:string[]) (y:string[]) (z:string[]) =
first
// |> Array.map (fun w -> Array.iter2 (fun x y -> (if w = x then y)) second third)
let fourth =
rplc first second third
printfn ""
printfn "fourth: %A" fourth
// Expected Result: fourth: [|"1"; "2"; "3"; "1"; "2"; "1"; "3"; "2"; "3"; "3"; "3"|]
// Actual Result: fourth: [|"A"; "B"; "C"; "A"; "B"; "A"; "C"; "B"; "C"; "C"; "C"|]
我的评论行失败但我不确定为什么?
答案 0 :(得分:1)
最简单的方法是从第二个和第三个数组创建一个查找表,而不是映射第一个数组的每个元素,并将其用作键。
let first = [|"A"; "B"; "C"; "A"; "B"; "A"; "C"; "B"; "C"; "C"; "C"|]
let second = [|"A"; "B"; "C"|]
let third = [|"1"; "2"; "3"|]
let lookupTbl = Map(Array.zip second third) //create a Map/Dictionary from the zipped values
first
|> Array.map (fun x -> lookupTbl.[x]) //Use the first array's values as keys
//val it : string [] = [|"1"; "2"; "3"; "1"; "2"; "1"; "3"; "2"; "3"; "3"; "3"|]
如果您不确定所有密钥是否存在,也可以使用TryFind
,但在您的情况下,这似乎并不合适。
您的原始案例不起作用,因为您尝试使用if
作为语句,因此它返回unit
(因为如果x不等于w,会发生什么)。
如果你想更接近你的原始结构,你可以模式匹配而不是if,然后删除不匹配。 Array.collect
将数组数组折叠为一个数组。 match
表达式与代码中的if
相同,但如果匹配则返回Some
值,否则返回None
。最后,我们用None
删除Some
和Array.choose
选项包装器。
let rplc (x:string[]) (y:string[]) (z:string[]) =
first
|> Array.collect (fun w ->
Array.map2 (fun x y ->
match (w = x) with
| true -> Some(y)
| _ -> None ) second third)
|> Array.choose id
let fourth =
rplc first second third
printfn ""
printfn "fourth: %A" fourth
// val fourth : string [] =
// [|"1"; "2"; "3"; "1"; "2"; "1"; "3"; "2"; "3"; "3"; "3"|]
// val it : unit = ()