从列表列表中删除整数对,同时保持原始顺序-Haskell

时间:2019-11-07 18:45:00

标签: haskell

我一直在努力从列表列表中删除重复项,同时保持其余部分和空白列表的原始位置。假设:

list1 = [[1],[2],[1,2],[4],[1,4]]
list2 =[[1],[2],[1,2],[4],[1,4],[2,4]]
list3 = [[1,2,4],[1,4],[2,4],[1,4],[1,2,4]]

然后输出应为:

[[],[],[],[],[1]]

[[],[],[],[],[1],[2,4]]

[[],[],[,],[],[2,4]]

(删除哪些对并不重要)

但是,只有先平整列表,然后再丢失空白列表的原始位置,我才能使此功能正常工作。如果有人知道如何解决这个问题,我将不胜感激!

代码很杂乱,但适用于平面列表:

remPair [] = []
remPair (x:xs) = if elem x xs then
                    let
                      n = elemIndices x xs
                      (ys, zs) = splitAt (head n) xs
                      in remPair (ys ++ (drop 1 zs))
                  else  [x] ++ remPair xs

1 个答案:

答案 0 :(得分:1)

正确的响应

我试图以Haskell-y的方式解决它,但是这段代码的性能很差,很难阅读。我只是想看看我是否可以解决问题。

import Data.List (elemIndices)

appendHead :: a -> [[a]] -> [[a]]
appendHead x [] = [[x]]
appendHead x (ys:yss) = (x:ys):yss

-- | count how many time an element occurs in a list of lists
count :: Eq a => a -> [[a]] -> Int
count _ [] = 0
count x (ys:yss) = (length $ elemIndices x ys) + count x yss

-- | assume count is 1 or greater for simplicity
rmAllButLast :: Int -> Int -> [[Int]] -> [[Int]]
rmAllButLast x xCount yss =  
  if xCount == 0
  then yss
  else
    let protectLastElement cond = if even xCount then cond else True in
    snd $
    foldl
    (\(xIndex,acc) ys ->
        (\y -> acc++[y]) <$> foldl
        (\(xIndex,acc) y ->
           if protectLastElement (xIndex < xCount-1) && x == y
           then (xIndex+1, acc)
             else (xIndex, acc++[y]))
        (xIndex, [])
        ys
    )
    (0, [])
    yss

rmPairs :: [[Int]] -> [[Int]]
rmPairs [] = []
rmPairs ([]:yss) = [] : rmPairs yss
rmPairs ((x:xs):yss) =
  let xCount = count x (xs:yss) in
  if xCount == 0
  then appendHead x $ rmPairs (xs:yss)
  else rmPairs $ rmAllButLast x xCount (xs:yss)

旧回复

编辑:下面的代码不是作者想要的,但是我将其保留,以便下面的注释有意义。

如果您要删除重复项(一次或多次发生的任何事情都将减少为一个值)或实际对(此值有两个,那么如果有偶数,则将它们都删除),我不是100% x,则将它们全部删除,如果它是x的奇数,则将有一个)。假设是前者,而不考虑性能:

remPair :: [[Int]] -> [[Int]]
remPair []       = []
remPair ([]:yss) = [] : remPair yss
remPair (xs:yss) = remPairFromFlat xs : remPair yss
  where
    flatYss = concat yss
    remPairFromFlat []     = []
    remPairFromFlat (z:zs) =
      let flat = zs ++ flatYss in
      if z `elem` flat
      then remPairFromFlat zs
      else z : remPairFromFlat zs

remPair遍历列表列表。如果第一个列表不为空,则将列表的其余部分变平,然后遍历xs的元素,并创建ys的本地平面列表和xs的尾部。 / p>