Я пытался заменить данную существующую книгу новой книгой в списке. Новая книга должна иметь название, страницы, рейтинг и показывать, сколько раз ее одалживали каждую неделю с 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]]

Например, если я заменю книгу «Гарри Поттер» 374 9,7 [7, 5, 8] на книгу «Дон Кихот» 304 8,9 [4, 6, 3] I должен получить результат:

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
-1
Галена Колева 26 Апр 2020 в 16:41

2 ответа

Лучший ответ

Если вы хотите удалить или добавить книгу, map не может вам помочь: свойство map заключается в том, что оно не может изменить количество элементов в списке. Однако есть еще один способ реализовать это с помощью map: просто отобразить каждый элемент списка книг, проверить, равна ли каждая книга вашей старой книге, и, если она есть, заменить ее новой книгой: map (\b -> if b == oldBook then newBook else b) bookList . Это должно позволить вам заменить oldBook на newBook без изменения порядка элементов.

(Одна небольшая проблема: если у вас есть дубликаты книг, это в конечном итоге заменит обе одинаковые книги, а не только одну. Если это проблема для вас, вам нужно будет использовать другой подход - в этой ситуации я бы использовал рекурсия . )

3
bradrn 26 Апр 2020 в 14:22

Все зависит от того, что вы хотите архивировать. Если вы хотите заменить все вхождения данной книги, функция карты в порядке. Однако, если вы хотите заменить только первый, лучше использовать что-то вроде:

replaceBook :: Book -> Book -> [Book] -> [Book]
replaceBook _ _ [] = []
replaceBook old new (x:xs)
  | old == x  = new:xs
  | otherwise = x:replaceBook old new xs
0
Janusz Czornik 26 Апр 2020 в 19:06