繁体   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