2011-03-13 18 views
6

gelen her n eleman kaldırılsın mı?bir dize her n eleman çıkarmanın nasıl dize

Sana şekilde çeşit drop işlevini kullanın tahmin ediyorum. Bu birinci n düşer gibi

, nasıl bu kadar üzerinde değil, hepsinden daha bu yüzden ancak bundan sonra nth ve sonra n'inci damla değiştirebilir ve ki? take ve drop birleştirmek

dropthem n xs = drop n xs 

cevap

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
İşte

işlevi yaptığı da budur:

zip [1..] listedeki endekse tüm öğeleri kullanılır, bu nedenle örneğin zip [1..] "foo", [(1,'f'), (2,'o'), (3,'o')] olur.

Dizinlenmiş liste daha sonra n tarafından dizinine bölünemeyen her öğeyi biriktiren bir right fold ile işlenir.

Burada aslında aynı şeyi yapan biraz daha uzun bir sürüm var, ancak zip [1..] ek bellek ayırmalarını önler ve modül hesaplaması gerekmez.

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

yerine' zip' ve 'mod' dizenin – Peaker

+0

'remove_every_nth n = harita snd. filtre ((/ = 0). (\ 'mod \ n) fst). Posta [1 ..] ' – Alvivi

+0

@Peaker: öneri için teşekkür ederiz. "Zip" kullanmadan döngüyü nasıl kullanacağınızdan emin değilim, ama verimliliği biraz farklı bir şekilde geliştirdim. 'RemoveEveryNth n = haritası snd:' cycle' ile – shang

2

deneyin bunu başarmak için.

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

Mesajım içinde bir hata yaptım, şimdi bunu aldım ve listeden nth değerini kaldırır. Listemden her value değeri kaldırmak istedim, bu yüzden bazı özyineleme eklemem gerektiğini tahmin ediyorum? veya filtre? – Lunar

+0

@Lunar, siz "her n değeri" ne demek istiyorsunuz? – luqui

+0

örn: 4 "thisiscool" bu 'cycle' [kullanmayın neden biraz pahalı yanlış cevap – 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

basit. (N-1) elementlerini alın, ardından 1'i atlayın, durulayın ve tekrarlayın.

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

veya verimlilik aşkına gösterir tarzda

aşağıdaki çözüm gibi

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

:

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

Sadece hangi grupların uzunluktaki bölümler halinde bir liste bir işlevi group tanımlamak zorunda n. Ama bu oldukça kolay:

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

hlint öneririm concat yerine 'concatMap' kullanarak. map' –