У меня есть два списка — один представляет собой список кортежей сетки, а другой — список координат — для сравнения, так что список координат всегда является подсписком списка сетки. Теперь я хочу проверить каждый кортеж в списке сетки, находится ли он в списке координат или нет. Если он существует, замените кортеж в списке сетки на «#», а если нет, замените на «_».
Ниже моя лучшая попытка, и она никогда не работает.
getHash :: [(Int,Int)] -> [(Int,Int)] -> [String]
getHash [(x1,y1)] [(x2,y2)] | (x1,y1) `elem` [(x2,y2)] : (x1,y1) = "#"
| otherwise (x1,y1) = "_"
where (x1,y1) <- [(x1,y1)]
@LouisWasserman Должен ли я создать новый тип для (x, y)
и использовать имя xy1
в функции?
Нет, вам не нужно создавать какие-либо типы.
Вы хотите заменить каждый элемент в списке на "#"
или "_"
в зависимости от того, является ли этот элемент элементом второго списка. Мы можем разделить это на две части. Первая часть «Заменить каждый элемент в списке результатом вызова функции с этим элементом в качестве аргумента» — это map
. Второй, выполнение чего-либо на основе того, является ли элемент элементом списка, действительно использует elem
. Так что мы будем
map
над списком иelem
на каждом элементе,elem
.getHash known xs = map (\x -> if x `elem` known then "#" else "_") xs
Итак, почему я сначала привел известный список? В основном это личные предпочтения, но я думаю, что это работает немного лучше при частичном применении. getHash [(1,2)]
— это функция, которая сравнивает список, заданный в качестве аргумента, со статическим «известным» списком. И так как xs
является правильным положением для него, мы также можем использовать редукцию эта в определении:
getHash known = map (\x -> if x `elem` known then "#" else "_")
[(x1,y1)]
соответствует только списку, содержащему ровно одну пару координат. Если вы хотите просмотреть произвольный список, вам понадобится одно имя переменной, напримерxy1
, без каких-либо скобок или круглых скобок. (В более общем плане вы, кажется, боретесь с наличием скобок и синтаксиса в неподходящих местах.)