2011-03-13 20 views
6

¿Cómo se puede eliminar cada enésimo elemento de una cadena?Eliminar cada elemento n de la cadena

Supongo que usaría la función drop de alguna manera.

Al igual que la primera n, ¿cómo se puede cambiar esto para que solo se elimine la enésima y luego la enésima, y ​​así sucesivamente, en lugar de todo?

dropthem n xs = drop n xs 

Respuesta

2
remove_every_nth :: Int -> [a] -> [a] 
remove_every_nth n = foldr step [] . zip [1..] 
    where step (i,x) acc = if (i `mod` n) == 0 then acc else x:acc

Esto es lo que hace la función:

zip [1..] se utiliza para indexar todos los elementos de la lista, por lo que, por ejemplo, zip [1..] "foo" se convierte en [(1,'f'), (2,'o'), (3,'o')].

La lista indexada se procesa con un right fold que acumula cada elemento cuyo índice no es divisible por n.

Aquí hay una versión un poco más larga que hace esencialmente lo mismo, pero evita las asignaciones de memoria extra de zip [1..] y no necesita calcular el módulo.

remove_every_nth :: Int -> [a] -> [a] 
remove_every_nth = recur 1 
    where recur _ _ []  = [] 
      recur i n (x:xs) = if i == n 
      then recur 1 n xs 
      else x:recur (i+1) n xs
+0

en lugar de '' zip' y mod' que es un poco caro, por qué no usar 'cycle' [ 1..n] y comparar con 1? – Peaker

+0

'remove_every_nth n = map snd. filter ((/ = 0). (\ 'mod \' n). fst). zip [1 ..] ' – Alvivi

+0

@Peaker: Gracias por la sugerencia. No estoy seguro de cómo utilizarías 'cycle' sin usar' zip', pero mejoré un poco la eficiencia de una manera diferente. – shang

2

tratar de combinar take y drop para lograr esto.

take 3 "hello world" = "hel" 
drop 4 "hello world" = "o world" 
+0

cometí un error en mi publicación, lo tengo ahora, y quita el enésimo valor de mi lista. Quise eliminar cada enésimo valor de mi lista, así que supongo que necesito agregar alguna recursión. o filtro? – Lunar

+0

@Lunar, ¿qué quiere decir con "cada enésimo valor"? – luqui

+0

por ejemplo: 4 "thisiscool" cedía "thiiscol" su eliminado todos los elementos de la cadena de 4 – Lunar

4
-- groups is a pretty useful function on its own! 
groups :: Int -> [a] -> [[a]] 
groups n = map (take n) . takeWhile (not . null) . iterate (drop n) 

removeEveryNth :: Int -> [a] -> [a] 
removeEveryNth n = concatMap (take (n-1)) . groups n 
7

simple. Tome (n-1) elementos, luego salte 1, enjuague y repita.

dropEvery _ [] = [] 
dropEvery n xs = take (n-1) xs ++ dropEvery n (drop n xs) 

O en estilo muestra por el bien de la eficiencia

dropEvery n xs = dropEvery' n xs $ [] 
    where dropEvery' n [] = id 
      dropEvery' n xs = (take (n-1) xs ++) . dropEvery n (drop n xs) 
1

me gusta la siguiente solución:

del_every_nth :: Int -> [a] -> [a]  
del_every_nth n = concat . map init . group n 

sólo hay que definir una función group que agrupa una lista en porciones de longitud norte. Pero eso es bastante fácil:

group :: Int -> [a] -> [[a]] 
group n [] = [] 
group n xs = take n xs : group n (drop n xs) 
+0

hlint sugeriría usando 'concatMap' en lugar de' concat. mapa' –

Cuestiones relacionadas