Как я могу удалить уникальные элементы в списке? Хаскелл

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

["abc","abc","a","b","c","b"]

вернется:

["abc","b"]

В случае, если все элементы встречаются ровно один раз, будут возвращены все.

Если это поможет, я уже реализовал функцию сортировки.


person Arthur    schedule 16.12.2014    source источник


Ответы (3)


После сортировки вы можете сопоставлять повторяющиеся элементы с образцом, отбрасывая все остальное.

dropSingles [] = []
dropSingles (x:y:rest) | x == y = x:dropSingles (dropWhile (== x) rest)
dropSingles (x:rest) = dropSingles rest 
person jamshidh    schedule 16.12.2014
comment
@DiegoNolan- мой плохой, спасибо за улов. Это было исправлено. - person jamshidh; 17.12.2014
comment
Часть фильтра не делает то, что я хочу. Он просто удаляет элементы списка с отдельными символами, не удаляя элементы списка, которые встречаются только один раз. - person Arthur; 17.12.2014
comment
Спасибо, не могли бы вы объяснить, что делает последняя строка? - person Arthur; 17.12.2014
comment
@Arthur- в основном, он фактически отбрасывает одиночный .... Случай с двойным значением уже был сопоставлен выше, так что это значение по умолчанию, оно сопоставляется с одинарным, затем игнорирует только что сопоставленное значение x и рекурсивно отбрасывает одиночные числа на остальные. - person jamshidh; 17.12.2014

Как насчет этого?

import Data.List

getDups :: Ord a => [a] -> [a]
getDups = map head . filter (\l -> length l > 1) . group . sort

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

person DiegoNolan    schedule 16.12.2014
comment
Это очень полезно, однако можно ли сделать это без использования группы, учитывая, что мне нужно использовать только функции прелюдии? Если нет, думаю, можно попробовать реализовать. - person Arthur; 17.12.2014

import Data.List

f xs = case nub (xs \\ nub xs) of
    []  -> xs
    xs' -> xs'

main = do
    print $ f ["abc","abc","abc","a","b","c","b"] -- ["abc","b"]
    print $ f ["abc","a","c","b"]                 -- ["abc","a","c","b"]

т.е. удалить каждый элемент один раз, а затем вернуть каждый элемент один раз.

person user3237465    schedule 17.12.2014
comment
Кратко, но nub несколько абсурдно неэффективно. - person dfeuer; 17.12.2014