2015-12-17 3 views
0

Привет, мне было интересно, как использовать функцию map и filter в haskell, чтобы получить количество цифр в списке. Это было путано, вот пример.Карта и фильтр, Haskell

let a = [[1,2,1,2,1,1,1],[1,2],[3,4],[3,2]] 

И я хочу использовать map, чтобы узнать, сколько 1s в каждом подсписком поэтому результат будет

[5,1,0,0] 

Любая идея, как это сделать, я предполагаю, что его легко и им просто не хватает что-то, ура, мой подход

let ones = map(\x length (filter (\z -> z == 1)x))a 

, но это становится все ошибки

+5

Вы должны опубликовать свой подход. –

+0

Это почти правильно, вам просто не хватает -> after \ x – Ctx

+1

У вас есть синтаксические ошибки в коде. В первом лямбда-выражении отсутствует '->'. –

ответ

1

Препятствуйте проблеме в малые шаги.

Шаг 1. Подсчитайте количество 1 в списке. Сделайте функцию count1s :: [Int] -> Int с использованием length и filter.

Шаг 2. Используйте map для применения count1s к каждому списку во внешнем списке.

3

Сначала получите функцию фильтра:

((==) 1) 

Это будет фильтровать все другие элементы, чем 1 из списка:

filter ((==) 1) 

Затем соединить его с функцией длины через функцию состава:

(length . filter ((==) 1)) 

Наконец, сопоставьте массив списков с этой функцией, и все готово !

map (length . filter ((==) 1)) 
0

Вы писали:

let ones = map(\x length (filter (\z -> z == 1)x))a 

Очень хорошая попытка, и почти правильно! Давайте вставим его в GHCi, он отходит обратно:

<interactive>:9:35: Parse error in pattern: \ z -> z == 1 

Так что это значит? Это означает, что он думает, что он смотрит на шаблон и что ему не удалось читать it (разбор текста). Если мы просто посмотрим на это, это не шаблон! Почему он думает, что он смотрит на образец?

Из-за более раннего \x, за которым не последовал ->. В аргументах функции literal вам разрешено сопоставлять шаблоны! Вы можете написать \(y:_) x -> y + x, и это будет то же самое, что и (+) . head, взяв главу одного списка и добавив его ко второму предоставленному номеру.

Вставка его получаем:

let ones = map(\x -> length (filter (\z -> z == 1)x))a 

Что дает дополнительную ошибку:

<interactive>:10:55: Not in scope: ‘a’ 

Это потому, что я забыл явно определить a, так что это легко исправить:

let ones a = map(\x -> length (filter (\z -> z == 1)x))a 

Скомпилирует, а затем:

Prelude> ones [[1,2,1,2,1,1,1],[1,2],[3,4],[3,2]] 
[5,1,0,0] 

по желанию. Но мы еще не закончили, давайте упростим!

Прежде всего \z -> z == 1, который проще писать с использованием operator sections как (1 ==). Я бы рекомендовал всегда помещать в это пространство, чтобы он выглядел немного «неполным».

Тогда \x -> length (filter (1 ==) x) также немного многословие, мы можем использовать function composition operator., чтобы написать его как length . filter (1 ==). Если вы запутались в приоритет здесь, помните, что скобки всегда бывают первыми, затем функции, затем операторы ... так что это (.) length (filter (1 ==)), если вы действительно это записали.

Как только у вас есть это, дайте ему имя и подпись типа в исходном файле!

countOnes :: (Eq a, Num a) => [a] -> Int 
countOnes = length . filter (1 ==) 

Тогда я написал бы map countOnes везде, где вы на самом деле с помощью этого кода.

Смежные вопросы