Карта и фильтр в Haskell - PullRequest
       5

Карта и фильтр в Haskell

1 голос
/ 12 февраля 2012

У меня есть два списка кортежей: [(String,Integer)] и [(Float,Integer)].Каждый список имеет несколько кортежей.

Для каждого Integer, который имеет Float во втором списке, мне нужно проверить, соответствует ли его Integer Integer в первом списке, иделает, возвращает String - хотя эта функция должна возвращать список String с, то есть [String] со всеми результатами.

Я уже определил функцию, которая возвращает список Integer s из второго списка (для сравнения по целым числам в первом списке).

Это должно быть решено с помощью "функций высокого порядка".Я потратил значительное количество времени на игры с map и filter, но не нашел решения!

Ответы [ 3 ]

6 голосов
/ 12 февраля 2012

У вас есть список Integers из второго списка.Давайте назовем это ints.

Теперь вам нужно сделать две вещи: во-первых, отфильтровать список (String, Integer), чтобы он содержал только пары с соответствующими целыми числами в списке ints, а во-вторых, включитьlist в просто список String.

Эти два шага соответствуют filter и map соответственно.

Во-первых, вам нужна функция для фильтрации.Эта функция должна принимать пару (String, Integer) и возвращать, если целое число находится в списке ints.Поэтому он должен иметь тип:

check :: (String, Integer) -> Bool

Написание этого не должно быть слишком сложным.Получив его, вы можете просто отфильтровать по нему первый список.

Далее вам понадобится функция для преобразования пары (String, Integer) в String.Это будет иметь тип:

extract :: (String, Integer) -> String

Это также должно быть легко написать.(Стандартная функция, подобная этой, на самом деле существует, но если вы только учитесь, полезно разобраться с ней самостоятельно.) Затем вам нужно сопоставить эту функцию с результатом вашего предыдущего фильтра.

Надеюсь, это даствам достаточно намеков, чтобы получить решение самостоятельно.

3 голосов
/ 12 февраля 2012

В этом примере видно, как важно точно описать проблему не только для других, но и для самого себя.

Вы хотите строки из первого списка, чье связанное целое число встречается во втором списке.

При таких проблемах важно делать решения небольшими шагами. Чаще всего никто не может написать функцию, которая делает это сразу, но это то, что многие новички считают, что они должны делать.

Начните с написания сигнатуры типа, необходимой для вашей функции:

findFirsts :: [(String, Integer)] -> [(Float, Integer)] -> [String]

Теперь, из описания проблемы, мы можем сделать вывод, что нам, по сути, нужно сделать две вещи:

  1. Преобразование списка (String, Integer) в список String
  2. Выберите записи, которые мы хотим.

Следовательно, основной каркас нашей функции выглядит следующим образом:

findFirsts sis fis = map ... selected
    where
        selected = filter isWanted sis
        isWanted :: (String, Integer) -> Bool
        isWanted (_,i) = ....

Вам понадобятся функции fst, elem и snd для заполнения пустых мест.

Примечание: лично я предпочел бы решить эту проблему с помощью понимания списка, что часто приводит к более удобочитаемому (для меня, во всяком случае) коду, чем комбинация карты и фильтра с нетривиальными критериями фильтрации.

1 голос
/ 12 февраля 2012

Половина проблемы состоит в том, чтобы получить список строк, если у вас есть одно целое число.Существуют различные возможности сделать это, например, используя filter и map.Однако вы можете объединить обе операции, используя «сложение»:

findAll x axs = foldr extract [] axs where
   extract (a,y) runningList | x==y = a:runningList
                             | otherwise = runningList

--usage: 
findAll 2 [("a",2),("b",3),("c",2)]
--["c","a"]

Для сгиба у вас есть начальное значение (здесь []) и операция, которая последовательно объединяет рабочие значения со всеми элементами списка:начиная слева (foldl) или справа (foldr).Здесь эта операция extract, и вы используете ее, чтобы решить, добавлять ли строку из текущего элемента в рабочий список или нет.

После выполнения этой части другая половина тривиальна: вам нужнополучите целые числа из списка (Float,Integer), вызовите findAll для всех из них и объедините результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...