5
votes

Toutes les combinaisons non dupliquées de deux éléments de liste

Il est plus facile d'expliquer cela avec un exemple:

Je veux écrire une fonction [a] -> [(a, a)] donc si j'obtiens une liste

function s = [(x,y) | x <- s, y <- s]


2 commentaires

Quelle est la sortie pour [A, A, A, A] ?


Je pense que cela implique que les éléments sont uniques (conceptuellement un ensemble).


4 Réponses :


5
votes

Solution utilisant la récursivité:

[(head x, y) | x <- tails xs, y <- x]

Sans récursivité:

import Data.List (tails) 

f'' :: [a] -> [(a, a)]
f'' xs = concatMap (\sl -> zip (repeat $ head sl) sl) (tails xs)

Sans compréhension de liste:

import Data.List (tails) 

f' :: [a] -> [(a, a)]
f' xs = concat [[(head x, y) | y <- x] | x <- tails xs]


2 commentaires

Pourquoi concat alors que vous êtes déjà dans une compréhension de liste? f 'xs = [(tête x, y) | x <- tails xs, y <- x] . Et puis la prochaine question évidente est: pourquoi utiliser head lorsque la correspondance de motifs fera l'affaire? f 'xs = [(h, y) | x @ (h: _) <- tails xs, y <- x] .


Ce serait mieux, d'accord, même si je pense que l'utilisation de head est bien.



0
votes

Poursuivant l'idée du filtre [(x, y) | x , vous pouvez le faire en utilisant foldl à la place:

f = foldl add [] 
  where add ys (a,b) | notElem (b,a) ys = (a,b):ys 
                     | otherwise = ys

g xs = [(x,y) | x <- xs, y <- xs]

function = f . g


0 commentaires

1
votes

Vous pouvez utiliser scanr

f l = zip l (scanr (:) [] l) >>= \(h,t) -> fmap ((,) h) t

Vous obtenez d'abord la liste des (têtes, queues) de l , les queues de carte appariant leurs éléments avec la tête correspondante et enfin aplatir tout.


0 commentaires

2
votes

C'est une boucle imbriquée.

import Data.List (dropWhile)

com xs = do
  x <- xs
  y <- dropWhile (/= x) xs
  return (x, y)


0 commentaires