[英]Haskell: Removing element from list of lists of tuples by a tuple
我的代碼中有一個結構,其中包含一個包含多個列表的列表,然后這些列表具有表示坐標的元組。 這是我的情況:
type Point = (Int, Int)
type ShipPoints = [Point]
removeCoordinatePairFromList :: Point -> [ShipPoints] -> [ShipPoints]
removeCoordinatePairFromList fireCoordinate enemyShips = (filter (notElem fireCoordinate) enemyShips)
然而,這並不像我想要的那樣工作。 這將刪除找到匹配坐標對的父列表中的整個子列表。 我希望只從子列表中刪除與 fireCoordinate 匹配的一個元組,其他所有內容保持不變。 上下文是戰艦游戲,ShipPoints 類型表示列表中任何類型的船舶坐標。 [ShipPoints] 表示來自一名玩家的所有船舶坐標。
看起來您想要查看ShipPoints
列表並從它出現的每個ShipPoints
中刪除該Point
。 這可以通過map
完成:
removePointFromShipList :: Point -> [ShipPoints] -> [ShipPoints]
removePointFromShipList p lst = map (removePointFromShip p) lst
這使用了一個輔助函數:
removePointFromShip :: Point -> ShipPoints -> ShipPoints
從特定ShipPoints
中刪除Point
。 這個輔助函數可以用過濾器定義:
removePointFromShip p shp = filter (/= p) shp
我認為上述功能很簡單,不需要真正改進,但是由於 Haskell 程序員不能完全獨立,大多數(包括我)會嘗試重構它。 隨意忽略這部分或只是瀏覽它以獲得樂趣。
無論如何,許多 Haskeller 會將removePointFromShip
函數移動到where
子句中,並可能縮短名稱:
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p lst = map removePoint' lst
where removePoint' shp = filter (/= p) shp
然后,許多人會認識到,如果您有fx = blah blah blah x
,您可以將其替換為f = blah blah blah
(一個稱為 eta-reduction 的過程)。 主函數和輔助函數都可以像這樣進行 eta-reduce:
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p = map removePoint'
where removePoint' = filter (/= p)
現在,有一個where
子句是沒有意義的where
所以:
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint p = map (filter (/= p))
這很好,大多數人都會停在這里。 真正的瘋子會認識到有機會通過寫作將其轉變為“無點”形式:
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint = map . filter . (/=)
(從技術上講,這與之前的版本並不相同,但只要p /= q
始終與q /= p
相同就可以了。)現在,它看起來很聰明,但沒有人可以僅通過查看來理解它它,所以我們必須添加一個評論:
-- Remove Point everywhere it appears in [ShipPoints]
removePoint :: Point -> [ShipPoints] -> [ShipPoints]
removePoint = map . filter . (/=)
驚人的!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.