拆分清单并从子列表中获取总和? [英] Split list and make sum from sublist?

查看:92
本文介绍了拆分清单并从子列表中获取总和?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有一个数字列表,我需要为列表的每一部分返回SUM。例如:

初始列表:[1,2,3,0,3]部分除以0我需要使用FOLDL函数。

,4,0,5,2,1]

sublist [[1,2,3],[3,4],[5,2,1]]

结果[6,7,7]

我有一个在初始列表中找到0的函数:

  findPos list = [index + 1 | (index,e)<  -  zip [0 ..] list,e == 0] 

(从例子返回初始列表[4,6])

以及使用FOLDL进行SUM的函数:

  sumList list = foldl(+)0 list 

完全没有把它放在一起:/ b / b>

----我的解决方案

最后我发现了一些完全不同的东西,你们建议。

花了我整整一天的时间:/ b / b
$ b

  groups :: [Int]  - > [Int] 
groups list = [sum x | x< - makelist list]

makelist :: [Int] - > [[Int]]
makelist xs = reverse(foldl(\acc x - > zero x acc)[[]] xs)

zero :: Int - > [[Int]] - > [[Int]]
zero x acc | x == 0 = addnewtolist acc
|否则= addtolist x acc

addtolist :: Int - > [[Int]] - > [[Int]]
addtolist i listlist =(i:(head listlist)):(drop 1 listlist)

addnewtolist :: [[Int]] - > [[Int]]
addnewtolist listlist = []:listlist


解决方案 div>


现在您已经完成了自己的问题,我向您展示了一个稍微不太详细的版本。 Foldr 在我看来对这个问题*更好,但是因为您要求 foldl 我会向您展示我的解决方案这两个函数。

另外,你的例子似乎不正确,[5,2,1]的总和是8,而不是7。



foldr 版本。

  makelist'l = foldr(\ x(n:ns) - > if x == 0 then 0:(n:ns)else(x + n):ns)[0] l $在这个版本中,我们遍历这个列表,如果当前元素(x)是一个0,我们就添加一个新的元素(b)累加器列表中的新元素(n:ns)。否则,我们将当前元素的值添加到累加器前部元素的值中,并用此值替换累加器的前部值。 

Step by步:


  1. acc = [0],x = 1。结果是[0 + 1]

  2. acc = [1],x = 2。结果是[1 + 2]

  3. acc = [3],x = 5.结果为[3 + 5]

  4. acc = [8],x = 0。结果是0:[8]

  5. acc = [0,8 ],x = 4。结果是[0 + 4,8]

  6. acc = [4,8],x = 3 。结果是[4 + 3,8]

  7. acc = [7,8],x = 0结果为0: [7,8]

  8. acc = [0,7,8],x = 3.结果是[0 + 3, 7,8]

  9. acc = [3,7,8],x = 2。结果是[3 + 2,7 ,8]

  10. acc = [5,7,8],x = 1。结果是[5 + 1,7, 8] = [6,7,8]

你有它!



foldl 版本。与上面类似,但产生一个反向列表,因此在此函数的开头使用reverse来反向列表。

  

*从右侧折叠列表允许cons(:)函数自然使用,使用我的方法与左折叠产生一个反向列表。 (可能有一种更简单的方式来做左侧的折叠版本,我没有想到这会消除这种小小的变化。)


im searching for a solution for my Haskell class.

I have a list of numbers and i need to return SUM for every part of list. Parts are divided by 0. I need to use FOLDL function.

Example:
initial list: [1,2,3,0,3,4,0,5,2,1]
sublist [[1,2,3],[3,4],[5,2,1]]
result [6,7,7]

I have a function for finding 0 in initial list:

findPos list = [index+1 | (index, e) <- zip [0..] list, e == 0] 

(returns [4,6] for initial list from example)

and function for making SUM with FOLDL:

sumList list = foldl (+) 0 list

But I completely failed to put it together :/

---- MY SOLUTION
In the end I found something completely different that you guys suggested.
Took me whole day to make it :/

groups :: [Int] -> [Int]
groups list = [sum x | x <- makelist list]

makelist :: [Int] -> [[Int]]
makelist xs = reverse (foldl (\acc x -> zero x acc) [[]] xs)  

zero :: Int -> [[Int]] -> [[Int]]
zero x acc | x == 0 = addnewtolist acc
           | otherwise = addtolist x acc

addtolist :: Int -> [[Int]] -> [[Int]]
addtolist i listlist = (i : (head listlist)) : (drop 1 listlist)

addnewtolist :: [[Int]] -> [[Int]]
addnewtolist listlist = [] : listlist

解决方案

Now that you've completed the problem on your own, I am showing you a slightly less verbose version. Foldr seems better in my opinion to this problem*, but because you asked for foldl I will show you my solution using both functions.

Also, your example appears to be incorrect, the sum of [5,2,1] is 8, not 7.

The foldr version.

makelist' l = foldr (\x (n:ns) -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l

In this version, we traverse the list, if the current element (x) is a 0, we add a new element to the accumulator list (n:ns). Otherwise, we add the value of the current element to the value of the front element of the accumulator, and replace the front value of the accumulator with this value.

Step by step:

  1. acc = [0], x = 1. Result is [0+1]
  2. acc = [1], x = 2. Result is [1+2]
  3. acc = [3], x = 5. Result is [3+5]
  4. acc = [8], x = 0. Result is 0:[8]
  5. acc = [0,8], x = 4. Result is [0+4,8]
  6. acc = [4,8], x = 3. Result is [4+3,8]
  7. acc = [7,8], x = 0. Result is 0:[7,8]
  8. acc = [0,7,8], x = 3. Result is [0+3,7,8]
  9. acc = [3,7,8], x = 2. Result is [3+2,7,8]
  10. acc = [5,7,8], x = 1. Result is [5+1,7,8] = [6,7,8]

There you have it!

And the foldl version. Works similarly as above, but produces a reversed list, hence the use of reverse at the beginning of this function to unreverse the list.

makelist l = reverse $ foldl (\(n:ns) x -> if x == 0 then 0:(n:ns) else (x + n):ns) [0] l

*Folding the list from the right allows the cons (:) function to be used naturally, using my method with a left fold produces a reversed list. (There is likely a simpler way to do the left fold version that I did not think of that eliminates this triviality.)

这篇关于拆分清单并从子列表中获取总和?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆