7
votes

Fonction de carte si un prédicat contient

Je me sens comme ça devrait être assez évident, ou facile, mais je ne peux tout simplement pas l'obtenir. Ce que je veux faire, c'est appliquer une fonction à une liste (en utilisant la carte code>) mais uniquement si une condition est maintenue. Imaginez que vous ne vouliez que diviser les chiffres qui étaient même:

map (`div` 2) (even) [1,2,3,4]


0 commentaires

6 Réponses :


11
votes

Si vous ne voulez pas définir une fonction séparée, utilisez Lambda. xxx pré>

ou au lieu d'une carte, la compréhension de la liste, un peu plus lisible, je pense. P>

[if (even x) then (x `div` 2) else x | x <- [1,2,3,4]]


3 commentaires

@PPioTrlegnica: Dans ce cas, la compréhension de la liste peut être mauvaise pour la performance, car elle se traduit par ConcatMap qui provoque la création d'une couche superflue de listes.


@Fuzxxl: Exécutez GHC -DDDOMP-SIMPLE , vous verrez qu'aucune liste intermédiaire n'est créée. La valeur par défaut Réécrire les règles et autres passes d'optimisation sont plus intelligents que cela.


Oui. J'ai oublié cela. GHC est damné intelligent, parfois même si intelligente de retirer les barrages routiers que je mets pour bloquer son optimisation ... :)



9
votes
mapIf p f = map (\x -> if p x then f x else x)

1 commentaires

Notez que cela peut être transformé en un utilitaire plus général pour Foncteur S, non seulement listes, si vous modifiez mapper sur fmap dans ce qui précède.



3
votes

En plus de la réponse de PioTrlegnica: Souvent, il est plus facile de lire si vous déclarez une fonction d'assistance au lieu d'utiliser une Lambda. Considérons ceci: xxx pré>

( [1..4] code> est le sucre pour [1,2,3,4] code>) p>

Si vous souhaitez supprimer tous les autres éléments, envisagez d'utiliser Filtre code>. filtre code> supprime tous les éléments qui ne satisfont pas le prédicat: p> xxx pré>

afin que vous puissiez créer un tuyau de carte code> et Filtre que ou utilisez la compréhension de la liste à la place: P>

map (`div` 2) $ filter even [1..4]
[x `div` 2 | x <- [1..4], even x]


0 commentaires

2
votes

Créez votre propre fabricant de fonctions d'assistrage:

ifP pred f x = 
    if pred x then f x
    else x

custom_f = ifP even f
map custom_f [..]


1 commentaires

Personnellement, j'appellerais ce quand , puisque si me fait penser qu'il devrait y avoir un cas el / code> aussi, mais j'aime cette solution.



0
votes

Surtout une arnaque des réponses existantes, mais selon ma définition biaisée de "lisible" (j'aime les gardes plus que les ifs, et où code> plus que laisse code>):

ghci> let mapIf p f = map f' where f' x | p x = f x | otherwise = x
ghci> mapIf even (+1) [1..10]
[1,3,3,5,5,7,7,9,9,11]


0 commentaires

1
votes

J'aime les autres solutions plus générales, mais dans votre cas très spécial, vous pouvez vous éloigner avec

map (\x -> x `div` (2 - x `mod` 2)) [1..4]


0 commentaires