tengo una lista como estaHaskell lista de lista de tuplas
["peter","1000","michell","2000","kelly","3000"]
y me gustaría convertir a
[("peter",1000),("michell", 2000),("kelly",3000)]
Por favor, ayuda. Gracias.
tengo una lista como estaHaskell lista de lista de tuplas
["peter","1000","michell","2000","kelly","3000"]
y me gustaría convertir a
[("peter",1000),("michell", 2000),("kelly",3000)]
Por favor, ayuda. Gracias.
cnv :: [String] -> [(String, Integer)]
cnv [] = []
cnv (k:v:t) = (k, read v) : cnv t
Si desea manejar impar de longitud sólo tiene que añadir cnv [x] =
variante antes última
ony's solution es un poco más corto, pero aquí es una versión no recursiva utilizando splitEvery
de la muy práctico split
library:
cnv = map (\[name, amount] -> (name, read amount :: Int)) . splitEvery 2
Los pasos aquí son algo más claros (para mí, al menos) que en la versión recursiva.
Esto es definitivamente más natural. La biblioteca dividida no recibe suficiente amor. Es una lástima, ya que es increíblemente útil. –
Tenga en cuenta que 'splitEvery' parece estar en desuso ahora; utilice ['chunksOf'] (https://hackage.haskell.org/package/split-0.2.2/docs/Data-List-Split.html#v:chunksOf) en su lugar. – sevko
Exactamente para una tarea como esta me parece conveniente tener una función stride
tomar cada elemento n-ésimo de la lista:
stride _ [] = []
stride n (x:xs) = x : stride n (drop (n-1) xs)
Se puede utilizar para convertir una lista de pares:
toPairs xs = zip (stride 2 xs) (stride 2 (drop 1 xs))
Un ejemplo (tenga en cuenta que el último elemento puede ser desechado si no tiene pareja):
ghci> stride 2 [1..5]
[1,3,5]
ghci> toPairs [1..7]
[(1,2),(3,4),(5,6)]
Puede ser incluso extender fácilmente a trillizos o tuplas más largos:
toTriplets xs = zip3 as bs cs
where as = stride 3 xs
bs = stride 3 $ drop 1 xs
cs = stride 3 $ drop 2 xs
Para llevar a cabo la conversión de String
al número entero en su ejemplo, puede asignar read
función sobre el segundo paso:
let lst = ["peter","1000","michell","2000","kelly","3000"] in
zip (stride 2 lst) (map read . stride 2 . drop 1 $ lst) :: [(String,Int)]
cuales da:
[("peter",1000),("michell",2000),("kelly",3000)]
¿Puede explicar estas líneas de código cnv (k: v: t) = (k, leer v): cnv t? AFAIK, el k v t es un parámetro de la lista k es la cabeza yv es la cola y cnv t es el siguiente elemento como k. Es mi entendimiento correcto porque previamente tengo una función como esta. convertido :: [String] -> \t [(String, Integer)] convertido [] = [] convert (x: y: x) = (x, y) convertir XS y por qué cuando agrego: xs no está funcionando? ¿El k v t representa un solo elemento en la lista o lista completa? – peterwkc
No exactamente: en 'k: v: t',' k' es la cabeza, y 'v: t' es la cola. Por lo tanto, 'k: v: t' coloca los primeros dos elementos de la lista en' k' y 'v' y la cola restante en' t'. Su código tiene dos problemas obvios: (a) '(x, y)' tiene tipo '(String, String)', not '(String, Integer)'; y (b) no hay dos puntos antes de 'convert xs'. (No puede hacer ': xs', porque necesita' [(String, Integer)] 'pero' xs' tiene tipo '[String]'.) Además, un consejo de formateo: sangría las líneas con cuatro espacios en blanco para obtener bloques de código (o seleccionar su código y hacer clic en el botón "101010"), y rodear los fragmentos de código con barras invertidas (\ '... código ... \'). –
(x: xs) Eso significa que x es la cabeza y el resto del elemento es cola para xs. Gracias por su explicación. – peterwkc