2010-07-03 117 views
2

我試圖對位置列表中的每個位置(這是一個列表)進行排序。目前我doint這樣的:F#列表中的排序列表F#

type Position = Position of list<int * Piece> 

和我的功能:

let SortPositionList positionList : Position list = 
let rec loop list = 
    match (list: Position list) with 
    | [] -> [] 
    | hd::tl -> [List.sortBy(fun (x:(int*Piece)) -> fst x)(GetInternStruct(hd))::loop tl] 
loop positionList 

在我的腦海裏,這可以通過與其他recursivelly列表進行排序,實際的頭部,然後CONCAT它做的名單,但它不起作用。此功能中的錯誤爲:

類型不匹配。期待(INT *片)名單列表,但給出一個(INT *件)列表列表列表類型「詮釋*海賊王」不匹配的類型「(INT *片)名單」,在強調loop tl

類型不匹配。期望一個位置列表,但給出一個(int * piece)列表列表類型'位置'與類型'(int * piece)列表列表'不匹配,在下劃線調用循環中,loop positionList

希望你能幫助,在此先感謝

佩德羅Dusso

編輯 AList.map經過排序功能將是一個很好的形式給出?

SOLUTION

let SortPositionList (positionList : Position list) = 
    List.map (fun (Position(position)) -> List.sort(position)) positionList 

由於我的職位結構是一個爲(int *片)LST,我模式在anonimous功能匹配,並分類整理。

感謝您的答案!

回答

3

一般來說,在F#中有兩種處理方式。您可以明確使用遞歸,也可以使用現有函數。在你的情況下,你需要以嵌套的方式做兩件事 - 你需要迭代外部列表並對內部列表進行排序。可以使用List.sortBy完成排序,迭代(投影)可以使用List.map完成。

要糾正你原來的方法(使用遞歸) - 我simplfied稍微(因爲你不需要loop功能 - 可以使函數本身的遞歸):使用現有的功能

let rec sortPositionList list = 
    match list with 
    | [] -> [] 
    | hd::tl -> 
    // Sort the list of positions first - by storing this as a new value 
    // using 'let', you get more readable code (and you can use IntelliSense 
    // to explore the type of 'sorted' and understand what's going on) 
    let sorted = List.sortBy (fun (x, _) -> x) (GetInternStruct(hd)) 

    // As Brian suggests, more idiomatic F# encoding of the line would be: 
    // let sorted = GetInternStruct(hd) |> List.sortBy (fun (x, _) -> x) 
    // but both of the options would work in this case. 

    // Note: The result shouldn't be wrapped in '[ .. ]'. The operator '::' 
    // takes an element and a list and returns a new list created by 
    // prepending the element in front of the list 
    sorted::(sortPositionList tl) 

解決方案(List.map)已由JDU發佈。我只是補充說他使用了部分函數應用程序 - 所以傳遞給List.map的參數是一個函數。如果這種感覺混亂,你可以重寫明確規定,使用lambda表達式:

let SortPositionList (positionList) = 
    List.map (fun positions -> 
    List.sortBy (fun (index, _) -> index) positions) positionList 

哪位能使用流水線操作和fst函數,而不是明確的拉姆達參數(如布賴恩提到的)更慣用寫:

let SortPositionList (positionList) = 
    positionList |> List.map (fun positions -> 
    positions |> List.sortBy fst) 

這意味着與JDU發佈的代碼完全相同,但您可能會發現它更具可讀性。最後,您可以使用序列表達式寫同樣的事情(這也許是在我看來,最優雅的選項):

let SortPositionList (positionList) = 
    [ for positions in positionList do 
     yield positions |> List.sortBy fst ] 

編輯的功能,因爲我寫了他們在這裏與(int*Point) list list,而不是類型的值工作類型Positions list。要改變這一點,你需要添加一些包裝和解包。遞歸執行應該是:

match list with   // List is always 'Positions', so we use pattern 
    | Positions [] -> [] // matching to unwrap the underlying list in 
    | Positions (hd::tl) -> // both cases 
    // Wrap the resulting list into the positions type 
    let sorted = Positions(List.sortBy (fun (x, _) -> x) (GetInternStruct(hd))) 
    (sorted::(sortPositionList tl)) 

同樣,對於List.map實現:

let SortPositionList (positionList) = 
    positionList |> List.map (fun (Positions positions) -> // pattern matching 
    positions |> List.sortBy fst |> Positions) // wrapping 
+0

Tomas,我或多或少地理解你對''[']'所說的話,我有一個必須生成位置列表的函數。讓我們用board1 = Position [(1,Piece.BLACK);(2,Piece.WHITE);(6,Piece.BLACK ); ...] 例如,您提議的所有解決方案d對我來說,現在我更好地理解了慣用語。但是我應該如何解決這個問題?非常感謝Pedro Dusso(PS:我買了你的書!!! :) – 2010-07-04 00:21:34

+0

我不確定我完全按照你的描述 - 你有一個位置列表作爲輸入(這意味着你有一個列表元組'int * Piece')。你想得到什麼結果?你的原始問題似乎表明你想獲得排序位置的列表(這是一個包含元組排序列表的列表)。那是對的嗎? – 2010-07-04 00:30:36

+0

是的!這是正確的。函數工作完美,但因爲我需要使用元組進行排序,所以最終結果是一個(int * Piece)列表列表。如你所見,我的位置==(int * Piece)列表。所以我的最後一個問題是如何「投」這個,畢竟他們有我認爲相同的「結構」。感謝所有 – 2010-07-04 00:46:13

2

你做錯了。 :)

我不知道你想要做什麼,但看着你的代碼,我只知道它是錯的,所以這就是我所看到的。

首先,你必須

... List.sortBy blah1 blah2 ... 

這是不地道,你要

... blah2 |> List.sortBy blah1 ... 

將與類型推斷幫助。這有點侵入第二個問題,這是

(fun (x:(int*Piece)) -> fst x) 

是廢話。你可以寫

(fun (i:int,p:Piece) -> i) 

(fun (i,p) -> i) 

或只是

fst 

,它意味着同樣的事情,但你寫的是什麼難以理解的人(我,反正) 。我預計也許你首先陷入了困境,因爲沒有管道開始。最後,更多的是,在代碼示例中缺少空格也會使其不可讀;避免以往具有

)(

而不之間的空間,並使用更多的水平和垂直空白以使代碼的解析更加明顯。

這主要是文體和膚淺的反饋,但我認爲如果你解決這個問題,關於類型不深的深層問題將開始變得更有意義,並變得更加明顯。

+0

布賴恩,感謝您發表評論。我開始在F#世界,我真的讚賞這樣的反饋。我會盡力改善我的代碼可讀性以改進它。非常感謝。 – 2010-07-03 23:53:38

4

如何只:

let SortPositionList (positionList : Position list) = 
    List.map (fun pos -> List.sortBy (fun (index, _) -> index) pos) positionList 

什麼,那麼你正在使用的位置列表上List.map,繪製各元素(本身就是一個列表)到List.sortBy功能。這需要一個返回一個用於比較的鍵的函數。在這種情況下,我們使用內置的模式匹配來匹配'int * Piece'元組的索引。

+0

非常感謝JDU。最後,我寫了一個不同的代碼,但你的回答激勵我去做。再次感謝! – 2010-07-03 23:53:07

+0

我現在遇到的問題是這段代碼返回了一個(int * Piece)列表清單:(我知道我的位置是「(int * Piece)list」,但是如何使代碼(ou在後面投它)返回一個位置列表? – 2010-07-04 00:01:18

+0

你的意思是你想先將結構扁平化爲一個列表然後進行排序? – JDU 2010-07-04 00:11:37

1
let apply f (Position xs) = Position(f xs) 
let sorts = List.map (apply List.sort)