如何编写一个返回数组y中数组索引数组的函数?

fs_*_*ech 2 f#

我正在尝试编写一个有效的算法,它将有效地让我合并数据集(如sql join).我想我需要使用Array.tryFindIndex,但语法让我迷失了.

根据下面的数据,我调用arrX我的"主机"数组,并希望返回一个有长度的int数组,并告诉我arrY中每个元素的位置(如果不在那里则返回-1) .(一旦我知道这些索引,我就可以在长度为arrY.length的数据数组上使用它们)

let arrX= [|"A";"B";"C";"D";"E";"F"|]
let arrY = [|"E";"A";"C"|];


let desiredIndices = [|1; -1; 2; -1; 0; -1|]
Run Code Online (Sandbox Code Playgroud)

看起来我需要以某种方式使用选项类型,我认为那里也有mapi2.有谁知道怎么做到这一点?(我认为对于那些合并来自不同来源的数据集的人来说,这可能是一个非常有用的代码片段)

谢谢!

//This code does not compile, can't figure out what to do here
let d = Array.tryFindIndex (fun x y -> x = y) arrX
Run Code Online (Sandbox Code Playgroud)

Tom*_*cek 6

该tryFindIndex函数搜索指定为第二个参数的数组中的单个元素.lambda函数只获取一个参数,true如果参数是您要查找的元素,它应该返回.tryFindIndex函数的类型签名显示:

('a -> bool) -> 'a [] -> int option
Run Code Online (Sandbox Code Playgroud)

(在你的例子中,你给它一个带有两个类型参数的函数'a -> 'a -> bool,它与预期的类型不兼容).该tryFindIndex函数返回一个选项类型,这意味着它会None在没有元素与谓词匹配的情况下为您提供,否则它会为您提供Some(idx)找到的元素的索引.

要获得所需的索引数组,需要为tryFindIndex输入数组的每个元素运行(arrX).这可以使用该Array.map功能完成.如果要在未找到元素的情况下获得-1,则可以使用模式匹配转换None为-1并Some(idx)转至idx:

let desired = 
  arrX |> Array.map (fun x ->
    let res = Array.tryFindIndex (fun y -> x = y) arrY 
    match res with 
    | None -> -1 
    | Some idx -> idx)
Run Code Online (Sandbox Code Playgroud)

可以使用序列表达式(而不是map)来编写相同的东西,这可能更具可读性:

let desired = 
  [| for x in arrX do 
       let res = Array.tryFindIndex (fun y -> x = y) arrY 
       match res with 
       | None -> yield -1 
       | Some idx -> yield idx |]
Run Code Online (Sandbox Code Playgroud)

无论如何,如果你需要实现类似连接的操作,你可以更简单地使用序列表达式.在下面的示例中,我还添加了一些值(除了字符串键),以便您可以更好地了解它的工作原理:

let arrX= [|"A",1; "B",2; "C",3; "D",4; "E",5; "F",6|] 
let arrY = [|"E",10; "A",20; "C",30|]

[| for x, i in arrX do 
    for y, j in arrY do
      if x = y then 
        yield x, i, j |]

// Result:   [|("A", 1, 20); ("C", 3, 30); ("E", 5, 10)|]
Run Code Online (Sandbox Code Playgroud)

序列表达式简单地遍历所有arrX元素,并且对于每个元素,它遍历所有arrY元素.然后它测试键是否相同,如果它们是,它产生一个单独的元素.这不是特别有效,但在大多数情况下,它应该工作正常.