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

时间:2010-03-01 19:25:32

标签: 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|]

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

谢谢!

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

2 个答案:

答案 0 :(得分:6)

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

('a -> bool) -> 'a [] -> int option

(在您的示例中,您将为其提供一个函数,该函数采用类型为'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)

可以使用序列表达式(而不是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 |]

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

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)|]

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

答案 1 :(得分:3)

编写一个自定义函数,如果没有找到则返回-1,如果找到则返回索引。接下来,使用Array.map使用此函数映射新数组:

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

let indexOrNegativeOne x =
    match Array.tryFindIndex (fun y -> y = x) arrY with
    | Some(y) -> y
    | None -> -1

let desired = arrX |> Array.map indexOrNegativeOne
printfn "%A" desired