haskell - Haskell 用新数据替换列表中的数据
问题描述
我一直在尝试用列表中的新书替换给定的现有书。新书应该有一个名字、页数、评级,并且应该用 3 个数字显示它每周被借出的次数。更换后的书籍顺序应相同。
data Book = Book { name:: String
, pages:: Int, rating:: Float
, timesLentEveryWeek:: [Float]
} deriving (Eq,Ord,Show,Read)
testData1 :: [Book]
testData1 = [Book "Harry Potter" 374 9.7 [7, 5, 8],
Book "Percy Jackson & the Olympians" 530 9.8 [3 , 4, 2],
Book "Star Wars" 435 9.5 [9 , 7, 10]]
例如,如果我将Book "Harry Potter" 374 9.7 [7, 5, 8]替换为Book "Don Quixote" 304 8.9 [4, 6, 3]我应该得到结果:
Book "Don Quixote" 304 8.9 [4, 6, 3],
Book "Percy Jackson & the Olympians" 530 9.8 [3 , 4, 2],
Book "Star Wars" 435 9.5 [9 , 7, 10]]
我试图通过添加 removeBook 递归函数并通过使用该map
函数将元素从一个列表添加到另一个来添加一本书来解决该问题。但是,我没有使用此功能的经验,而且我似乎在实现它时遇到了问题:
removeBook :: String -> [Book] -> [Book]
removeBook n (p:ps)
| n == name p = removeBook n ps
| otherwise = p : removeBook n ps
replaceBook :: Book -> Book -> [Book] -> String -> [Book]
replaceBook old new booksData oldBookName = map new removeBook oldBookName booksData
解决方案
如果你想删除或添加一本书,map
帮不了你:一个属性map
是它不能改变列表中元素的数量。但是,还有另一种方法可以实现这一点map
:只需映射书籍列表的每个元素,检查每本书是否与您的旧书相同,如果是,则将其替换为新书:map (\b -> if b == oldBook then newBook else b) bookList
。这应该让您在不更改元素顺序的情况下替换oldBook
为newBook
。
(一个小问题:如果你有重复的书,这最终会替换两本相同的书,而不仅仅是一本。如果这对你来说是个问题,你将需要使用不同的方法——在这种情况下,我会使用递归。)
推荐阅读
- azure-ad-b2c - Azure B2C 自定义策略中的多个自定义标头和路径变量
- google-chrome - 使用服务器端设置 cookie,服务器删除它们,仍在后续请求中
- r - JSON 到 CSV(仅从 JSON 文件中获取第一行)
- angular - 在 Ionic 中选择性别之前,如何禁用该按钮?
- filemaker - 在 FileMaker Pro 19 中的现有记录之间添加新关系
- svg - Dagre svg 水平滚动条
- sparql - 查找应该是实例 sparql 的类;查找恰好有 1 个子类的类
- kotlin - 如何在kotlin中解密由openssl enc -a -e -aes-256-cbc加密的字符串?
- python - 如何添加具有不同 x 值的 y 值?
- python - 使用 CSV.QUOTE_NONNUMERIC 而不引用标题