Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何将具有重复项的数组转换为具有重复项之和的数组?_List_Haskell - Fatal编程技术网

List 如何将具有重复项的数组转换为具有重复项之和的数组?

List 如何将具有重复项的数组转换为具有重复项之和的数组?,list,haskell,List,Haskell,所以我已经为此挣扎了几个小时了。我有这个数组[[4,2]],[[1,2],[1,1]]],我想把这个数组转换成[[4,2]],[[1,3]] 因此,类型为f::[[[Integer]]->[[[Integer]]]] 问题 我有一个内部数组长度为2的2d数组:[[x,y]..] 如果内部数组的头元素重复,则该数组是重复的:[[1,2],[1,1]] 如果有重复项,我想取所有尾部的总和,创建一个新数组,头部作为重复值,重复项的总和作为尾部值:[[1,2],[1,1]变成[[1,3]] 我所拥有的

所以我已经为此挣扎了几个小时了。我有这个数组
[[4,2]],[[1,2],[1,1]]]
,我想把这个数组转换成
[[4,2]],[[1,3]]

因此,类型为
f::[[[Integer]]->[[[Integer]]]]

问题 我有一个内部数组长度为2的2d数组:
[[x,y]..]
如果内部数组的头元素重复,则该数组是重复的:
[[1,2],[1,1]]
如果有重复项,我想取所有尾部的总和,创建一个新数组,头部作为重复值,重复项的总和作为尾部值:
[[1,2],[1,1]
变成
[[1,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]]]`

这是我所能做的最好的。请帮助我!我不知道如何得到期望的结果。

(初步注释:如果你的最内层列表总是有两个元素,你应该考虑,如<代码> [[(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
将为您提供一个四层嵌套列表——一个由分组的两个元素列表组成的列表。下一步是通过挤压组,从而删除重复项,将其变回三层嵌套列表。这可以通过折叠完成,通过两层映射应用(以便折叠的列表是最里面的列表组):

需要注意的一点是,
groupBy
仅对相邻元素进行分组,因此您有:

GHCi> sumOfSample [[[4,2],[4,4]],[[1,2],[2,1],[1,1]]]
[[[4,6]],[[1,2],[2,1],[1,1]]]

如果这是不可接受的,那么解决这一问题是可能的,尽管这可能非常烦人,并且/或者需要一种不同的方法(除非您不关心“中间层”内部列表中的顺序,否则您可以简单地使用
ifDuplicateGroup=map(groupBy dup.sort)sample
,正如Renezee在评论中指出的那样)

深度列表使代码难以理解。使用类型别名是否有帮助

这是我的临时解决方案

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
耶尔德


如果
Pair
只有两个成员,例如
[a,b]
,你应该使用tuple
(a,b)
并使用
fst
snd
而不是
head
tail
来澄清一个细节:如果你的内部列表中有一个类似于
[1,2],[3,4]的内容,该怎么办
?2d数组没有任何内容保持不变。
[[1,2],[3,4]]
类型应该少一个列表深度,因此
f:[[[Integer]]]->[[[Integer]]]]]
。您可以使用
sort
(或通用的
sortBy
)解决
map(map(foldl1'dedup.).groupBy dup.sort)之类的问题
。在这种情况下,
sort
可以很好地工作,因为它对元素从头到尾进行排序。@Renzeee确实如此。我考虑过提到这一点,但考虑到问题中使用的措辞,我怀疑“中间层”内部列表的顺序对OP很重要。无论如何,我想作为脚注添加这一点并没有什么坏处。
-- 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)
GHCi> sumOfSample [[[4,2],[4,4]],[[1,2],[2,1],[1,1]]]
[[[4,6]],[[1,2],[2,1],[1,1]]]
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]]