当前位置: 首页 > 知识库问答 >
问题:

根据Haskell列表中n的条件删除元素n-1、n和n1

长孙鸿波
2023-03-14

所以假设我有一个从220的所有整数的列表。

[2 .. 20]

我想用一个函数过滤列表(或者它是谓词?我不太习惯Haskell编程中使用的所有术语)。如果此函数的位置n等于true,我想删除位置n-1、n和1的元素。

示例:假设列表[2...20]中位置4的元素等于6,对于函数f等于true。然后我想删除位置345的元素,它们分别等于567。所以我的最终列表如下所示:

[2,3,4,8,9,10,11,12,13,14,15,16,17,18,19,20]

我是一个没有经验的Haskell程序员,只是为了好玩。我想过使用lambda函数作为谓词,但我不太确定如何去做。我还想过使用像删除xs ys这样的函数来删除xs中的所有元素,这也是ys的元素,但我也不确定如何做到这一点。

任何帮助将不胜感激!

编辑:我意识到为了产生我想要的结果而删除两个相邻的元素是错误的。此外,最好只是将受影响元素(位于位置n和n-1的元素)的值更改为0,或者以其他方式标记/标记它们,而不是完全删除它们。原因是我想一直“删除”元素,直到列表中不再有任何适合谓词的元素(及其前面的元素)。我只想从原始列表中“删除”它们。由于我的方法与原来的问题有很大的不同,我将发布一个新的问题来反映我的新方法。我想感谢你的所有回答,我从你的回答中学到了很多。非常感谢。

编辑2:这是我的新问题:当n适合谓词时,删除Haskell列表中位置n和n-1的元素

共有3个答案

南宫凯康
2023-03-14

我的解决方案使用小自制列表拉链实现:

-- List zipper (think of this as a standard library routine):
data LZ a = LZ [a] a [a] deriving (Show)

listToLZ :: [a] -> LZ a
listToLZ (h:t) = LZ [] h t

lzToList :: LZ a -> [a]
lzToList (LZ l p r) = reverse l ++ p:r

moveRight, remLeft, remRight, remHere :: LZ a -> LZ a
moveRight (LZ l t (t':r)) = LZ (t:l) t' r
remLeft (LZ l p r) = LZ (tail l) p r
remRight (LZ l p r) = LZ l p (tail r)
remHere (LZ l _ (p:r)) = LZ l p r

-- And there's how one use this:
-- <business code>
traverse :: (a -> Bool) -> LZ a -> LZ a
traverse _ a@(LZ _ _ []) = a
traverse pr a@(LZ _ p _) 
   | pr p = traverse pr $ remHere $ remRight $ remLeft a
   | True = traverse pr $ moveRight a
-- </business code>

main = let
  l = [1..20]
  l' = lzToList $ traverse (==4) $ listToLZ l
in
  print l'

输出:

[1,2,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

吕翰飞
2023-03-14

这里有一种方法,但我相信还有更优雅的方法。

方法是首先将我们的列表[a]映射到三元组[(可能a, a,可能a)]的列表。(可能开始发挥作用,因为第一个和最后一个元素分别缺少前身/后继。)

然后,我们可以根据我们在这个三元组类型上构造的谓词邻接ntf来实现一个过滤器。(请注意,与标准过滤器相比,您请求的过滤器是向后的——当谓词为true时,您希望删除内容。)

preprocess :: [a] -> [(Maybe a, a, Maybe a)]
preprocess xs = zip3 (beforeXs xs) xs (afterXs xs)

beforeXs :: [a] -> [Maybe a]
beforeXs xs = Nothing : (map Just xs)

afterXs :: [a] -> [Maybe a]
afterXs xs = concat [(map Just (tail xs)), [Nothing]]

middle3 :: (a, b, c) -> b
middle3 (_,x,_) = x

myfilter :: (a -> Bool) -> [a] -> [a]
myfilter f xs = map middle3 $ filter (not . adjacentF) (preprocess xs)
    where
        maybeF = maybe False f
        adjacentF (x,y,z) = (maybeF x) || (f y) || (maybeF z)

一般来说,这应该会产生预期的结果:

*Main> myfilter (==20) [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
*Main> myfilter (==1) [1..20]
[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
*Main> myfilter (==5) [1..20]
[1,2,3,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
*Main> myfilter (\x -> x >= 12 && x <= 14) [1..20]
[1,2,3,4,5,6,7,8,9,10,16,17,18,19,20]
*Main> myfilter even [1..20]
[]
马银龙
2023-03-14

您可以在多个元素上进行模式匹配,并将过滤器应用于中间的元素。

eitherside :: (Int->Bool) -> [Int] -> [Int]
eitherside f (i1:i2:i3:is) = if (f i2) 
    then eitherside f is 
    else i1 : (eitherside f (i2:i3:is))
eitherside f is = is
*Main> eitherside (==4) [1..10]
[1,2,6,7,8,9,10]
*Main> eitherside (==5) [1..10]
[1,2,3,7,8,9,10]
*Main> eitherside (==6) [1..10]
[1,2,3,4,8,9,10]

不是这样(我原来的帖子):

eitherside :: (Int->Bool) -> [Int] -> [Int]
eitherside f (i1:i2:i3:is) = if (f i2) 
    then eitherside f is 
    else [i1,i2,i3] ++ (eitherside f is)
eitherside f is = is
*Main> eitherside (==5) [1..10]
[1,2,3,7,8,9,10]

这个糟糕的错误恰好适用于5,但由于我在“else”分支中跳过了它,所以在6中失败了。

 类似资料:
  • 问题内容: 我有一个清单清单: 我想从列表中删除所有不满足条件的元素。 因此,如果我想删除与之相对应的元素。 所以list_1将被修改为 我该如何选择性地做到这一点? 问题答案: 您也可以根据需要使用该条件。

  • 问题内容: 我已经看过这篇文章: Python:通过删除每个第n个元素从现有列表构建新列表,但是由于某些原因,它对我不起作用: 我这样尝试: 此函数需要一个列表和。然后,它使用列表中的n步删除第n个元素,并打印结果。 这是我的函数调用: 错误的输出: 代替 然后我从上面的链接尝试了一个变体: 再次,函数调用: 给了我同样的错误的结果: 不是 如何正确地从列表中删除/删除/删除 第n个 项目? 问题

  • 我有一个这样的数字列表: 如何以优雅的方式总结每个N(让我们假设2)个元素并将列表转换为: 编辑:我想出了以下解决方案: 它是有效的,但我仍然在寻找一个更易读、更简单的方法。

  • 我有一个包含和以及的字符串。 我们如何删除和,同时保持机智?

  • 本文向大家介绍在C ++中找到(1 ^ n + 2 ^ n + 3 ^ n + 4 ^ n)mod 5,包括了在C ++中找到(1 ^ n + 2 ^ n + 3 ^ n + 4 ^ n)mod 5的使用技巧和注意事项,需要的朋友参考一下 在本教程中,我们将解决以下问题。 给定一个整数n,我们必须找到(1 n +2 n +3 n +4 n)%5 如果n大,则数字(1 n +2 n +3 n +4

  • 所以我有超过1000000列 但我只需要前10000列,基本上将列从n(int)降至n(int)。谢谢!