Otra idea sería decir: el último dígito cuenta para 1, el penúltimo cuenta para 10, el dígito anterior cuenta para 100, etcétera. Por lo tanto, para convertir una lista de dígitos en un número, debe invertirlo (para comenzar desde atrás), multiplicar los dígitos junto con las potencias correspondientes de diez y sumar el resultado.
Para invertir una lista, utilice reverse
, para obtener las potencias de diez que puede utilizar iterate (*10) 1
(probarlo en GHCi o abrazos!), Para multiplicar los dígitos correspondientes de dos listas utilizar zipWith (*)
y añadir todo junto, utilice sum
- ¡realmente ayuda conocer algunas funciones de la biblioteca! Poner los trozos juntos, se obtiene
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Ejemplo de evaluación:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
Sin embargo, esta solución es más lento que los que tienen foldl
, debido a la llamada a reverse
y ya que estamos construyendo esos poderes de diez solo para usarlos directamente de nuevo. En el lado positivo, esta forma de construir números está más cerca de la forma en que la gente suele pensar (¡al menos yo lo hago!), Mientras que las soluciones foldl
en esencia usan Horner's rule.
O way cooler point free - fromDigits = foldl ((+). (* 10)) 0 :) –
¡Impresionante! Funciona perfectamente. Esto fue lo que pensé que tendría que hacer, pero lo has hecho mucho mejor de lo que pude, ¡gracias! – Paul
Así que funciona, pero no estoy muy seguro de cómo funciona la pieza addDigit. Sé que foldl toma una función y una lista lo hace en todos los elementos de la lista ... pero addDigit parece multiplicar 0 (num) por 10 y luego agrega el elemento ... que simplemente agregará el elemento ... entonces ¿qué soy? ¿Me pierdo? – Paul