Удалите элементы индексом в haskell

Вот хороший способ помнить процесс, что каждый из них следует за этим, я использую при попытке решить, который лучше для моего обстоятельства.

DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);

и следующее должно быть легко предположить то, что это делает

DateTime i = value as DateTime;

в первом случае, если значение не может быть брошено, чем исключение выдается во втором случае, если значение не может быть брошено, я устанавливаюсь в NULL.

, Таким образом, в первом случае твердая остановка сделана, если сбои броска во втором броске, которым сделана мягкая остановка и Вы могли бы встретиться с NullReferenceException позже.

11
задан qba 14 November 2009 в 23:52
поделиться

7 ответов

Два совершенно разных подхода

  1. Вы можете использовать List.splitAt вместе с drop :

     import Data.List (splitAt)
    f :: [a] -> [a]
    f [] = []
    f xs = let (h, t) = splitAt 5 xs в h ++ f (падение 3 t)
    

    Теперь f [1..12] дает [1,2,3,4,5,9,10,11,12] . Обратите внимание, что эту функцию можно выразить более элегантно, используя uncurry и Control.Arrow.second :

     import Data.List (splitAt)
    import Control.Arrow (второй)
    f :: [a] -> [a]
    f [] = []
    f xs = uncurry (++) $ second (f. drop 3) $ splitAt 5 xs
    

    Поскольку мы все равно используем Control.Arrow , мы можем отказаться от splitAt и вместо этого вызвать помощь Control.Arrow. (&&&) в сочетании с take :

     import Control.Arrow ((&&&))
    f :: [a] -> [a]
    f [] = []
    f xs = uncurry (++) $ (возьмите 5 &&& (f. drop 8)) xs
    

    Но теперь ясно, что еще более короткое решение выглядит следующим образом:

     f :: [a] -> [a] 
    f [] = []
    f xs = взять 5 xs ++ (f. drop 8) xs
    

    Как отмечает Крис Лутц , это решение можно обобщить следующим образом:

     nofm :: Int -> Int -> [a] -> [a]
    nofm _ _ [] = []
    nofm nm xs = взять n xs ++ (nofm nm. drop m) xs
    

    Теперь nofm 5 8 возвращает требуемую функцию. Обратите внимание, что решение с splitAt может быть более эффективным!

  2. Примените некоторые математические данные, используя map , snd , filter ], mod и zip :

     f :: [a] -> [a]
    f = карта snd. фильтр (\ (i, _) -> i `mod` 8 <(5 :: Int)). zip [0 ..]
    

    Идея заключается в том, что мы объединяем каждый элемент в список в пары с его индексом, натуральным числом i . Затем мы удаляем те элементы, для которых i% 8> 4 . Общая версия этого решения:

     nofm :: Int -> Int -> [a] -> [a]
    nofm nm = карта snd. фильтр (\ (i, _) -> я `mod` m 
16
ответ дан 3 December 2019 в 01:29
поделиться
myRemove = map snd . filter fst . zip (cycle $ (replicate 5 True) ++ (replicate 3 False))
1
ответ дан 3 December 2019 в 01:29
поделиться

Поскольку никто не создавал версию с «разворачиванием», вот мой вариант:

drop3after5 lst = concat $ unfoldr chunk lst
  where
    chunk [] = Nothing
    chunk lst = Just (take 5 lst, drop (5+3) lst)

На данный момент кажется самым коротким

4
ответ дан 3 December 2019 в 01:29
поделиться

Это мое решение. Это очень похоже на ответ @ barkmadley , используя только take и drop , но с меньшим беспорядком, на мой взгляд:

takedrop :: Int -> Int -> [a] -> [a]
takedrop _ _ [] = []
takedrop n m l  = take n l ++ takedrop n m (drop (n + m) l)

Не уверен, что выиграет любые награды за скорость или сообразительность, но я думаю, что это довольно ясно и лаконично, и это определенно работает:

*Main> takedrop 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]
*Main> 
2
ответ дан 3 December 2019 в 01:29
поделиться

Вы можете легко подсчитать свои элементы:

strip' (x:xs) n | n == 7 = strip' xs 0
                | n >= 5 = strip' xs (n+1)
                | n < 5 = x : strip' xs (n+1)
strip l = strip' l 0

Хотя открытое кодирование выглядит короче:

strip (a:b:c:d:e:_:_:_:xs) = a:b:c:d:e:strip xs
strip (a:b:c:d:e:xs) = a:b:c:d:e:[]
strip xs = xs
5
ответ дан 3 December 2019 в 01:29
поделиться

Вот мое решение:

remElements step num=rem' step num
    where rem' _ _ []=[]
          rem' s n (x:xs)
              |s>0 = x:rem' (s-1) num xs
              |n==0 = x:rem' (step-1) num xs
              |otherwise= rem' 0 (n-1) xs

пример:

*Main> remElements 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]
1
ответ дан 3 December 2019 в 01:29
поделиться

функции take и drop могут помочь вам здесь.

drop, take :: Int -> [a] -> [a]

из них мы могли бы построить функцию, которая будет делать один шаг.

takeNdropM :: Int -> Int -> [a] -> ([a], [a])
takeNdropM n m list = (take n list, drop (n+m) list)

, а затем мы можем использовать это, чтобы уменьшить нашу проблему

takeEveryNafterEveryM :: Int -> Int -> [a] -> [a]
takeEveryNafterEveryM n m [] = []
takeEveryNafterEveryM n m list = taken ++ takeEveryNafterEveryM n m rest
    where
        (taken, rest) = takeNdropM n m list

*Main> takeEveryNafterEveryM 5 3 [1..20]
[1,2,3,4,5,9,10,11,12,13,17,18,19,20]

, так как это не примитивная форма рекурсии, сложнее выразить это как простую свертку.

так что новая функция сворачивания может быть определены в соответствии с вашими потребностями

splitReduce :: ([a] -> ([a], [a])) -> [a] -> [a]
splitReduce f []   = []
splitReduce f list = left ++ splitReduce f right
    where
        (left, right) = f list

, то определение takeEveryNafterEveryM просто

takeEveryNafterEveryM2 n m = splitReduce (takeNdropM 5 3)
2
ответ дан 3 December 2019 в 01:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: