如何为List.filter包含多个参数?
我需要在函数中添加一些参数作为过滤列表的谓词。
在F#中,List.filter只接受一个参数。但是,我需要为谓词添加多个参数才能工作。
就我而言,我需要添加 sourceX 和 sourceY 作为参数:
let jumpOptions space =
match space with
| Allocated p -> match p with
| Red (ch,xy) -> xy = (sourceX + 1, sourceY - 1) ||
xy = (sourceX - 1, sourceY - 1)
| Black (ch,xy) -> xy = (sourceX + 1, sourceY + 1) ||
xy = (sourceX - 1, sourceY + 1)
| _ -> false
let jumpsForSoldier piece positions =
match piece with
| Black (ch,pos) -> positions |> List.filter jumpOptions
| Red (ch,pos) -> positions |> List.filter jumpOptions
总之,我希望将列表中的元素保持为纯粹。因此,我不想将列表中的每个元素与其他值捆绑在一起以满足过滤函数。
任何指导?
附录
open NUnit.Framework
open FsUnit
(* Types *)
type Black = BlackKing | BlackSoldier
type Red = RedKing | RedSoldier
type Coordinate = int * int
type Piece =
| Black of Black * Coordinate
| Red of Red * Coordinate
type Space =
| Allocated of Piece
| Available of Coordinate
type Status =
| BlacksTurn | RedsTurn
| BlackWins | RedWins
(* Private *)
let private black coordinate = Allocated (Black (BlackSoldier , coordinate))
let private red coordinate = Allocated (Red (RedSoldier , coordinate))
let private yDirection = function
| Black _ -> -1
| Red _ -> 1
let private toAvailable = function
| Available pos -> true
| _ -> false
let available positions = positions |> List.filter toAvailable
let private availableSelection = function
| Available pos -> Some pos
| Allocated _ -> None
let private availablePositions positions =
positions |> List.filter toAvailable
|> List.choose availableSelection
let private allocatedSelection = function
| Allocated p -> match p with
| Red (ch,xy) -> Some xy
| Black (ch,xy) -> Some xy
| _ -> None
let private allocatedPositions positions =
positions |> List.filter toAvailable
|> List.choose allocatedSelection
let private getCoordinate = function
| Available xy -> Some xy
| _ -> None
let coordinateOf = function
| Black (checker , pos) -> pos
| Red (checker , pos) -> pos
let jumpOptions space =
match space with
| Allocated p -> match p with
| Red (ch,xy) -> let sourceX, sourceY = coordinateOf source
xy = (sourceX + 1, sourceY - 1) ||
xy = (sourceX - 1, sourceY - 1)
| Black (ch,xy) -> let sourceX, sourceY = coordinateOf p
xy = (sourceX + 1, sourceY + 1) ||
xy = (sourceX - 1, sourceY + 1)
| _ -> false
let jumpsForSoldier piece positions =
match piece with
| Black (ch,pos) -> positions |> List.filter jumpOptions
| Red (ch,pos) -> positions |> List.filter jumpOptions
let private isKing piece =
match piece with
| Black (checker , _) -> match checker with
| BlackSoldier -> false
| BlackKing -> true
| Red (checker , _) -> match checker with
| RedSoldier -> false
| RedKing -> true
(* Public *)
let startGame () =
[ red (0,0); red (2,0); red (4,0); red (6,0)
red (1,1); red (3,1); red (5,1); red (7,1)
red (0,2); red (2,2); red (4,2); red (6,2)
Available (1,3); Available (3,3); Available (5,3); Available (7,3)
Available (0,4); Available (2,4); Available (4,4); Available (6,4)
black (1,5); black (3,5); black (5,5); black (7,5)
black (0,6); black (2,6); black (4,6); black (6,6)
black (1,7); black (3,7); black (5,7); black (7,7) ] , BlacksTurn
let optionsFor piece positions =
let sourceX , sourceY = coordinateOf piece
let optionsForSoldier =
(fun pos -> pos = ((sourceX - 1) , (sourceY + (piece |> yDirection) )) ||
pos = ((sourceX + 1) , (sourceY + (piece |> yDirection) )))
let optionsForKing =
(fun pos -> pos = ((sourceX - 1) , (sourceY + 1 )) ||
pos = ((sourceX + 1) , (sourceY + 1 )) ||
pos = ((sourceX - 1) , (sourceY - 1 )) ||
pos = ((sourceX + 1) , (sourceY - 1 )))
match piece |> isKing with
| false -> positions |> availablePositions
|> List.filter optionsForSoldier
| true -> positions |> availablePositions
|> List.filter optionsForKing
let move piece destination positions =
let rec movePiece positions destinationXY =
let foundPiece = positions |> List.filter (fun space -> space = Allocated piece)
|> List.head
match foundPiece with
| Allocated (Black (ch, xy)) -> (positions |> List.filter (fun space -> space <> Allocated (Black (ch, xy)))
|> List.filter (fun space -> space <> destination))
@ [Available (xy) ; (Allocated (Black (ch, destinationXY)))]
| Allocated (Red (ch, xy)) -> (positions |> List.filter (fun space -> space <> Allocated (Red (ch, xy)))
|> List.filter (fun space -> space <> destination))
@ [Available (xy) ; (Allocated (Red (ch, destinationXY)))]
| _ -> positions
let options = optionsFor piece positions
let canMoveTo = (fun target -> options |> List.exists (fun xy -> xy = target))
match getCoordinate destination with
| Some target -> match canMoveTo target with
| true -> movePiece positions target
| false -> positions
| None -> positions
(* Tests *)
[<Test>]
let ``get jump options for red soldier`` () =
// Setup
let redPiece = Red ( RedSoldier , (0,2) )
let blackPiece = Black ( BlackSoldier , (1,3) )
let positions = [Allocated redPiece; Available (2,2); Available (4,2); Available (6,2)
Allocated blackPiece; Available (3,3); Available (5,3); Available (7,3)
Available (0,4); Available (2,4); Available (4,4); Available (6,4)]
// Test
positions |> jumpsForSoldier redPiece
|> should equal [Allocated blackPiece]
答案 0 :(得分:6)
您可以拥有任意数量的参数,然后将函数部分应用于除1之外的所有参数,并将结果传递给List.filter
。
let jumpOptions sourceX sourceY space = ...
...
positions |> List.filter (jumpOptions 5 42)
详细了解部分申请here。
答案 1 :(得分:1)
您可以使用模式匹配提取所需信息并使用部分应用(在TQBF评论后编辑的代码)
VS