2010-03-01 57 views
2

我想寫一個高效的算法,將有效地讓我合併數據集(如SQL連接)。我想我需要使用Array.tryFindIndex,但是語法讓我失去了。如何編寫一個函數,該函數返回數組y中數組x的值索引數組?

根據下面的數據,我打電話給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 

回答

6

tryFindIndex函數搜索指定爲第二個參數的數組中的單個元素。 lambda函數只獲取一個參數,如果參數是您正在查找的元素,它應返回true。該tryFindIndex函數的類型簽名表明這一點:

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

(在你的榜樣,你給它一個函數,'a -> 'a -> bool類型,這與預期的類型不兼容的兩個參數)。 tryFindIndex函數返回一個選項類型,這意味着如果沒有元素與謂詞相匹配,它會給你None,否則它給你Some(idx)包含找到的元素的索引。

要獲得所需的索引數組,您需要爲輸入數組的每個元素運行tryFindIndexarrX)。這可以使用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元素。然後它測試鍵是否相同,如果它們是,它會產生一個單一的元素。這並不是特別有效,但在大多數情況下,它應該可以正常工作。

+0

這是完美的 - 非常感謝 –

+0

很高興我可以幫助:-)。我還添加了一個關於使用序列表達式實現類似連接的操作的註釋。 –

+0

這是相當有用的 - 謝謝。順便說一句,我只是讀你的書,而現在正試圖寫代碼而不提及它(太多)。 –

3

編寫一個自定義函數,如果找不到任何內容,則返回-1;如果找到,則返回索引。接下來,使用Array。映射使用此功能映射一個新的陣列:

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 
+0

這太棒了 - 謝謝你 –