所以我现在几个小时都在苦苦挣扎。我有这个数组[[[4,2]],[[1,2],[1,1]]]
,我想将这个数组转换为[[[4,2]],[[1,3]]]
。
所以类型为f :: [[[Integer]]] -> [[[Integer]]]
我有一个2d数组,内部数组长度为2:[[x,y] .. ]
如果重复其head元素,则内部数组是重复的:[[1,2],[1,1]]
如果有重复项,我想取所有尾部的总和,并创建一个新的数组,其中head作为重复值,重复项的总和作为尾部值:[[1,2],[1,1]]
变为[[[1,3]]
dup [x,_] [y,_] = x == y
sample = [[[3,5],[2,3],[1,1]],
[[3,5],[2,3],[4,2],[1,2]],
[[3,5],[2,3],[4,2],[1,2]],
[[4,2],[1,2],[1,1]]]
ifDuplicateGroup = map (groupBy dup) sample
getSumOfDups n = map sum [concat $ map tail y | y <- n, (length y) > 1]
sumOfSample = map getSumOfDups sample
退货:
sumOfSample = [[],[],[],[3]]
期望的结果:
sumOfSample =
[[[3,5],[2,3],[1,1]],
[[3,5],[2,3],[4,2],[1,2]],
[[3,5],[2,3],[4,2],[1,2]],
[[4,2],[1,3]]]`
这是我能做的最好的事情。请帮忙!我无法弄清楚如何获得理想的结果。
答案 0 :(得分:4)
(初步说明:如果你的最里面的列表总是有两个元素,你应该考虑using pairs instead,就像var CONSTANTS = "https://www.test.com/api/";
var api = CONSTANTS+'api.php?method=register' + '&user_registration=';
$http.post(...)... // Same as above
一样。这样就不必处理不可能的情况或担心获取列表了您的函数无法处理的错误长度。也就是说,在下文中我将使用您最初提出的类型。)
虽然您未在[[(4,2)],[(1,2),(1,1)]]
中使用它,但您使用sumOfSample
走在了正确的轨道上:
ifDuplicateGroup
-- I have specialised the functions to Integer; they could be more general.
-- Also note that dup is partial; it only works with lists of two elements.
-- That is the sort of issue you might avoid by using pairs.
dup :: [Integer] -> [Integer] -> Bool
dup [x,_] [y,_] = x == y
-- Making it a function by not supplying 'sample'.
ifDuplicateGroup :: [[[Integer]]] -> [[[[Integer]]]]
ifDuplicateGroup = map (groupBy dup)
将为您提供一个四元组嵌套列表 - 一组分组的两元素列表。下一步是通过挤压组并因此删除重复项将其更改为三重嵌套列表。这可以通过折叠完成,通过两层映射应用(这样折叠的列表就是最里面列表的组):
ifDuplicateGroup
有一点需要注意:-- Combining function for the fold. Note that, just like dup, it is partial.
dedup :: [Integer] -> [Integer] -> [Integer]
dedup [x, acc] [_, y] = [x, acc + y]
-- foldl1' doesn't work with empty lists. That is not a problem here, given
-- that group does not produce empty (inner) lists.
sumOfSample :: [[[[Integer]]]] -> [[[Integer]]]
sumOfSample = map (map (foldl1' dedup)) . ifDuplicateGroup
-- Or, equivalently:
-- sumOfSample = map (map (foldl1' dedup) . groupBy dup)
只对相邻的元素进行分组,因此您就有了这样的:
groupBy
如果这是不可接受的,那么解决这个问题是可能的,尽管它可能非常烦人和/或需要一些不同的方法。 (除非你不关心“中间层”内部列表中的顺序,否则你可以简单地使用GHCi> sumOfSample [[[4,2],[4,4]],[[1,2],[2,1],[1,1]]]
[[[4,6]],[[1,2],[2,1],[1,1]]]
,正如Renezee在评论中指出的那样。)
答案 1 :(得分:3)
深层列表使代码难以理解。使用类型别名有帮助吗?
这是我的临时解决方案。
import Data.List
type Pair = [Int]
type PairList = [Pair]
sample :: [PairList]
sample = [[[3,5],[2,3],[1,1]],
[[3,5],[2,3],[4,2],[1,2]],
[[3,5],[2,3],[4,2],[1,2]],
[[4,2],[1,2],[1,1]]]
dupList :: PairList -> PairList
dupList xs = ss
where gs = groupBy dup xs
ss = map sumGroup gs
sumGroup :: PairList -> Pair
sumGroup xs = [h,t]
where h = head $ head xs
t = sum $ concatMap tail xs
dup :: Pair -> Pair -> Bool
dup xs ys = head xs == head ys
main :: IO ()
main = do
putStrLn "input"
mapM_ print sample
putStrLn "output"
let output = map dupList sample
mapM_ print output
一代产量
>runhaskell listlist.hs
input
[[3,5],[2,3],[1,1]]
[[3,5],[2,3],[4,2],[1,2]]
[[3,5],[2,3],[4,2],[1,2]]
[[4,2],[1,2],[1,1]]
output
[[3,5],[2,3],[1,1]]
[[3,5],[2,3],[4,2],[1,2]]
[[3,5],[2,3],[4,2],[1,2]]
[[4,2],[1,3]]
如果Pair
只有2名成员,例如[a,b]
,您应该使用元组(a,b)
并使用fst
,snd
代替head
,tail