0
votes

Comment puis-je additionner tous les 2 éléments d'une liste?

Essentiellement, je souhaite effectuer l'opération suivante: [1, 2, 3, 4, 5, 6, 7] -> [3, 7, 11, 7]

Dans l'exemple ci-dessus, l'élément à la fin de la liste est laissé seul car il n'y a rien avec quoi il peut être ajouté car la liste est de longueur impaire.

Je voulais transformer la liste en une liste de tuples comme [1, 2, 3, 4] -> [(1,2), (3,4)] puis effectuer l'addition sur chaque tuple, mais je ne pouvais pas comprendre comment faire cela, et je n'étais pas sûr que cela fonctionnerait avec une liste de longueur étrange.

Il existe sûrement un moyen d'ajouter tous les deux éléments dans une liste.


0 commentaires

3 Réponses :


1
votes

Un moyen simple de le faire est d'utiliser une définition récursive de base:

combinePairs :: (a -> a -> a) -> [a] -> [a]
combinePairs _ [] = []
combinePairs _ [x] = [x]
combinePairs _ (x:y:list) = f x y : combinePairs list

sumPairs :: Num a => [a] -> [a]
sumPairs = combinePairs (+)

Cependant, si vous souhaitez le faire en combinant des fonctions existantes, vous pouvez rechercher dans hoogle [a] -> [(a,a)] ( https://hoogle.haskell.org/?hoogle=%5Ba%5D+-% 3E +% 5B% 28a% 2Ca% 29% 5D & scope = set% 3Astackage ) pour voir s'il existe des fonctions pertinentes.

Malheureusement, il ne semble pas y en avoir. Certaines fonctions que vous pourriez écrire, si vous vouliez quelque chose de plus compositionnel, sont:

sumPairs :: Num a => [a] -> [a]
sumPairs = map getSum . mergePairs . map Sum

Ou, si vous vouliez être encore plus générique

pairUp :: Monoid a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, mempty)]
pairUp (x:y:list) = (x,y) : pairUp list

mergePairs :: Monoid a => [a] -> [a]
mergePairs = map (uncurry (<>)) . pairUp

puis

pairUp :: Num a => [a] -> [(a,a)]
pairUp [] = []
pairUp [x] = [(x, 0)]
pairUp (x:y:list) = (x,y) : pairUp list

sumPairs :: Num a => [a] -> [a]
sumPairs = map (uncurry (+)) . pairUp

Ou même

sumPairs :: Num a => [a] -> [a]
-- first, we deal with the base case
sumPairs [] = []
-- next we deal with the odd length list base case
sumPairs [x] = [x]
-- now we can recurse!
sumPairs (x:y:list) = (x+y) : sumPairs list


2 commentaires

En utilisant votre premier exemple, si je voulais changer la déclaration de fonction pour être quelque chose comme paires :: (Integer -> Integer -> Integer) -> [Integer] -> [Integer] et au lieu de sommer, effectuez un (+), ( -), (*), etc. opération. Comment changer la définition?


Tant pis, je l'ai compris! Je passe juste dans _ avec la liste vide et la liste impaire, puis passe dans f avec le fond de cas, puis fais sumPairs f list pour le morceau de récursivité. En fait, très simplement!



0
votes

Pour ce problème, je pense que je reviendrais à la récursivité explicite:

sumPairs :: Num a => [a] -> [a]
sumPairs (x:y:ys) = x+y:sumPairs ys
sumPairs xs = xs

Sympa et simple: s'il y a au moins deux éléments, additionnez-les puis répétez pour faire le reste. Sinon (ce qui signifie qu'il y a zéro ou un élément), retournez simplement la même liste que vous avez.


1 commentaires

Alors, que se passe-t-il exactement ici? Je suis encore assez nouveau dans Haskell, donc visualiser certaines de ces fonctions est assez difficile.



0
votes

Très court

map sum . chunksOf 2


0 commentaires