簡體   English   中英

Haskell:通過元組從元組列表中刪除元素

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM