Étant donné un nombre arbitraire, comment puis-je traiter chaque chiffre du numéro individuellement?
Edit J'ai ajouté un exemple de base du genre de chose que Foo
pourrait faire.
Par exemple, en C #, je pourrais faire quelque chose comme ceci:
static void Main(string[] args)
{
int number = 1234567890;
string numberAsString = number.ToString();
foreach(char x in numberAsString)
{
string y = x.ToString();
int z = int.Parse(y);
Foo(z);
}
}
void Foo(int n)
{
Console.WriteLine(n*n);
}
Avez-vous entendu parler de div et mod ?
Vous voudrez probablement inverser la liste des nombres si vous souhaitez d'abord traiter le chiffre le plus significatif. La conversion du nombre en chaîne est une manière altérée de faire les choses.
135 `div` 10 = 13
135 `mod` 10 = 5
Généraliser en fonction:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]
Ou en sens inverse:
digs :: Integral x => x -> [x]
digs 0 = []
digs x = x `mod` 10 : digs (x `div` 10)
Cela traite 0
comme n'ayant pas de chiffres. Une fonction wrapper simple peut traiter ce cas spécial si vous le souhaitez.
Notez que cette solution ne fonctionne pas pour les nombres négatifs (l'entrée x
doit être intégrale, c'est-à-dire un nombre entier).
digits :: Integer -> [Int]
digits = map (read . (:[])) . show
ou vous pouvez le renvoyer dans []
:
digits :: Integer -> [Int]
digits = map (read . return) . show
ou, avec Data.Char.digitToInt:
digits :: Integer -> [Int]
digits = map digitToInt . show
le même que celui de Daniel, mais sans point et utilise Int, car un chiffre ne doit pas vraiment dépasser maxBound :: Int
.
Vous pouvez également simplement réutiliser digits
de Hackage.
En utilisant la même technique utilisée dans votre message, vous pouvez faire:
digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)
Voyez-le en action:
Prelude> digits 123
[1,2,3]
Est ce que ça aide?
Déplier le manuel
import qualified Data.List as L
digits = reverse . L.unfoldr (\x -> if x == 0 then Nothing else Just (mod x 10, div x 10))
Vous pouvez utiliser
digits = map (`mod` 10) . reverse . takeWhile (> 0) . iterate (`div` 10)
ou pour l'ordre inverse
rev_digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)
La partie itérée génère une liste infinie divisant l'argument à chaque étape par 10, donc 12345 devient [12345,1234,123,12,1,0,0 ..]. La partie takeWhile ne prend que la partie non nulle intéressante de la liste. Ensuite, nous inversons (si nous le voulons) et prenons le dernier chiffre de chaque numéro de la liste.
J'ai utilisé un style sans point ici, vous pouvez donc imaginer un argument invisible n des deux côtés de "l'équation". Cependant, si vous voulez l'écrire de cette façon, vous devez remplacer le niveau supérieur .
par $
:
digits n = map(`mod` 10) $ reverse $ takeWhile (> 0) $ iterate (`div`10) n
Voici une amélioration par rapport à une réponse ci-dessus. Cela évite le 0 supplémentaire au début (Exemples: [0,1,0] pour 10, [0,1] pour 1). Utilisez la correspondance de motifs pour gérer les cas où x <10 différemment:
toDigits :: Integer -> [Integer] -- 12 -> [1,2], 0 -> [0], 10 -> [1,0]
toDigits x
| x < 10 = [x]
| otherwise = toDigits (div x 10) ++ [mod x 10]
J'aurais mis ceci dans une réponse à cette réponse, mais je n'ai pas les points de réputation nécessaires :(
Applicatif . sans point . Origami . Soigné.
Prendre plaisir:
import Data.List
import Data.Tuple
import Data.Bool
import Control.Applicative
digits = unfoldr $ liftA2 (bool Nothing) (Just . swap . (`divMod` 10)) (> 0)
Via la compréhension de la liste:
import Data.Char
digits :: Integer -> [Integer]
digits n = [toInteger (digitToInt x) | x <- show n]
production:
> digits 1234567890
[1,2,3,4,5,6,7,8,9,0]
J'étais paresseux pour écrire ma fonction personnalisée alors je l'ai googlé et tbh j'ai été surpris qu'aucune des réponses sur ce site Web n'ait fourni une très bonne solution - hautes performances et type sûr. Alors voilà, peut-être que quelqu'un voudrait l'utiliser. Fondamentalement:
[]
droite?)-XStrict
permet à Haskell d'effectuer une analyse de rigueur complète et d'optimiser la boucle interne.Prendre plaisir:
{-# LANGUAGE Strict #-}
digits :: Integral a => a -> NonEmpty Word8
digits = go [] where
go s x = loop (head :| s) tail where
head = fromIntegral (x `mod` 10)
tail = x `div` 10
loop s@(r :| rs) = \case
0 -> s
x -> go (r : rs) x
Pour avoir renvoyé une liste de [Entier]
import Data.Char
toDigits :: Integer -> [Integer]
toDigits n = map (\x -> toInteger (digitToInt x)) (show n)
La réponse acceptée est excellente mais échoue en cas de nombres négatifs car mod (-1) 10
est évalué à 9. Si vous souhaitez que cela gère correctement les nombres négatifs ... ce qui n'est peut-être pas le cas, le code suivant le permettra .
digs :: Int -> [Int]
digs 0 = []
digs x
| x < 0 = digs ((-1) * x)
| x > 0 = digs (div x 10) ++ [mod x 10]
La réponse acceptée est correcte, sauf qu'elle affichera une liste vide lorsque l'entrée est 0, mais je pense que la sortie doit être [0]
lorsque l'entrée est nulle.
Et je ne pense pas que cela traite du cas où l'entrée est négative. Voici ma mise en œuvre, qui résout les deux problèmes ci-dessus.
toDigits :: Integer -> [Integer]
toDigits n
| n >=0 && n < 10 = [n]
| n >= 10 = toDigits (n`div`10) ++ [n`mod`10]
| otherwise = error "make sure your input is greater than 0"