2016-03-30 2 views
3

Предоставление списка пар, напримерУдалить пара дублирует Haskell

[(1, 2), (1, 3), (1, 4), (2, 1), (3, 1), (4, 1)] 

Итак, я пытаюсь удалить пару дубликатов, я считаю пару, чтобы быть дубликатом, если (х, у) == (у , х), например: (1, 2) с (3, 1)

Я генерации список со списком понимания, это происходит из одного списка

MyList = [(intA, intB) | x <- integerList, y <- integerList, x /= y] 
integerList = [1, 2, 3]; 

Пожалуйста, обратите внимание, что Первое, что я написал, - всего лишь пример того, что Я хочу, чтобы это произошло, и это не выход из списка понимания выше.

Я недавно начал использовать Haskell, как бы я подошел к проблеме? Какой был бы лучший выбор? Я пробовал использовать карту, но без успеха мне следует объединить карту с foldl/foldr, в которой используется обратное внутри? Как мне это сделать?

+1

опечатка? '(1, 2) с (3, 1)' – karakfa

+0

Сначала напишите 'isPairDuplicate :: (Int, Int) -> (Int, Int) -> Bool' (затем опубликуйте его в своем вопросе, чтобы мы знали, говоря о). – jberryman

+0

Тогда я бы предложил подумать о написании рекурсивного решения, которое использует сопоставление шаблонов в списках и, возможно, «фильтр», если вы чувствуете себя сумасшедшим. – jberryman

ответ

3
import Data.List(nubBy) 
import Data.Tuple(swap) 

nubBy (\x y -> x==y || swap x == y) [(1, 2), (1, 3), (1, 4), (2, 1), (3, 1), (4, 1)] 
[(1,2),(1,3),(1,4)] 

или написать свои собственные версии

+0

Однако лучше решить проблему у источника в понимании списка. Я ответил на вопрос, основанный на описании названия и первого абзаца. – karakfa

8

Это идеальное время, чтобы использовать Hoogle! Давайте подумаем о том, что вы ищете. Чтобы удалить дубликаты, нам нужно что-то, что принимает список [a] и удаляет из него вещи, возвращая [a] на основе некоторого предиката a -> a -> Bool. Это означает, что мы ищем функцию с помощью следующей формы:

ourFunction :: (a -> a -> Bool) -> [a] -> [a] 

Мы можем фактически найти Hoogle с помощью функции подписи, (a -> a -> Bool) -> [a] -> [a] и первый результат nubBy, который делает именно то, что мы хотим!

Это, как говорится, вам не нужно использовать это, чтобы исправить вашу проблему. Вы уже на правильном пути. Подумайте о том, что вы просите - вы не хотите дублировать кортежи, где (x, y) == (y, x). Так просто выбрать, хотите ли вы y < x или наоборот, и использовать это в список вашего понимания:

> let fn xs = [(a, b) | a <- xs, b <- xs, a < b] 
> fn [1, 2, 3] 
[(1,2),(1,3),(2,3)] 

Если вам нужны оба списка (один с дубликатами и один без), я предложил бы использовать два отдельных список понятий. Это менее впечатляюще, так как понимание списка, которое вы написали, это O (n^2), но, с моей точки зрения, гораздо проще и легче учиться.

+1

Вот тот, который не требует экземпляра 'Ord' для элементов и не выполняет дополнительной работы, создавая неправильные элементы, а затем удаляя их:' fn xs = [(a, b) | a: xs '<- хвосты xs, b <- xs'] '. Я использовал этот стандартный трюк или небольшой вариант его довольно много раз в реальном коде. Конечно, у этой проблемы есть такая же проблема: если в списке ввода есть дубликаты, вывод будет тоже. –

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