我一直在努力从列表列表中删除重复项,同时保持其余部分和空白列表的原始位置。假设:
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
答案 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>