Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.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
Language agnostic 使用折叠的平均值_Language Agnostic_Functional Programming_Average - Fatal编程技术网

Language agnostic 使用折叠的平均值

Language agnostic 使用折叠的平均值,language-agnostic,functional-programming,average,Language Agnostic,Functional Programming,Average,如何使用map和reduce计算数字列表的平均值 理想情况下,我想打电话给名单上的reduce,得到一个平均值。您可以选择首先映射和过滤该列表 骨架LISP尝试: (defun average (list) (reduce ... list)) 一次尝试: function average (array) { return array.reduce(function() { .. }, 0); } 如果你用一种语言给出一个带有实际代码的答案,请把它解释成我是该语言的初学者

如何使用map和reduce计算数字列表的平均值

理想情况下,我想打电话给名单上的reduce,得到一个平均值。您可以选择首先映射和过滤该列表

骨架LISP尝试:

(defun average (list)
  (reduce ... list))
一次尝试:

function average (array) {
  return array.reduce(function() {
    ..
  }, 0);
}
如果你用一种语言给出一个带有实际代码的答案,请把它解释成我是该语言的初学者(我可能会是)

我想避免这个琐碎的回答

function average (array) {
   return sum(array) / array.length;
}
它在末尾使用除法,而不是reduce语句。我认为这是“作弊”。 [[编辑]]


解决了我自己的问题。如果有人使用LISP或Haskell中的语法糖提出了一个优雅的解决方案,我会感兴趣。

正如@abesto所提到的,它需要一个迭代算法

Let counter be 0 
For each [value, index] in list   
  let sum be (counter * index) + value   
  let counter be sum / (index + 1)

return counter
javascript实现将是

var average = function(list) { 
    // returns counter
    return list.reduce(function(memo, val, key) {
         // memo is counter
         // memo * key + val is sum. sum / index is counter, counter is returned
         return ((memo * key) + val) / (key + 1)
    // let counter be 0
    }, 0);  
}

描述Haskell中的一个apporach,它允许使用组合方法进行褶皱:

以下是common lisp的一个版本:

(defun running-avg (r v)
  (let* ((avg (car r))
         (weight (cdr r))
         (new-weight (1+ weight)))
    (cons (/ (+ (* avg weight) v) new-weight) new-weight)))

(car (reduce 'running-avg '(3 6 5 7 9) :initial-value '(0 . 0)))
;; evaluates to 6
它跟踪运行平均值和重量,并将新的平均值计算为
((以前的平均值*重量)+新值)

使用map和reduce计算数字列表的平均值

不需要
map
。只需展开以生成列表,并折叠以将其减少到平均值:

mean n m = uncurry (/) . foldr g (0, 0) . unfoldr f $ n
      where 
        f b | b > m     = Nothing
            | otherwise = Just (b, b+1)

        g x (s,n) = (s+x, n+1)
有效的实施

这种结构(
fold.unfold
)允许进行融合优化。一个特别有效的实现将融合展开(列表生成)和折叠(列表缩减)。这里,在Haskell中,GHC通过流融合将两个阶段(展开==
enumFromN
)和折叠结合起来:

import Data.Vector.Unboxed 

data Pair = Pair !Int !Double

mean :: Vector Double -> Double
mean xs = s / fromIntegral n
  where
    Pair n s       = foldl' k (Pair 0 0) xs
    k (Pair n s) x = Pair (n+1) (s+x)

main = print (mean $ enumFromN 1 (10^7))
编译器将其从两个函数的组合转换为递归循环:

main_loop a d e n =
    case ># a 0 of 
      False -> (# I# n, D# e #);
      True -> main_loop (-# a 1) (+## d 1.0) (+## e d) (+# n 1)
这将在汇编(编译器的C后端)中简化为此
goto

LLVM带来了更高效但更混乱的实现(大约快2倍)


参考文献:Mathematica中的

mean[l_List]:=
    Fold[{First@#1+1,(#2 +#1[[2]](First@#1-1))/First@#1}&,{1,1},l][[2]]  

In[23]:= mean[{a,b,c}]
Out[23]= 1/3 (a+b+c)

也许更适合CodeGolf.SE?一个简单的
reduce
aka
fold
不是
mapreduce
(如谷歌框架)。即使你事先把输入映射到地图上也不行。@delnan对不起,我把术语弄糊涂了。第一步应该是算出解决方案背后的数学。你能想出一个迭代算法来满足你的需求吗?将其转换为一个
折叠应该不会太难。@abesto解决方案现在看起来很简单。我没想谢谢你。你能解释一下
1+
weight
吗。我对LISP一无所知。另外,
*(carr r)(cdr r)
r
元组吗?
1+
是一个向参数添加1的函数
weight
只是一个局部变量名。是的,
r
是一个元组;通过创建一些有意义的名称,我对它进行了一些清理。这是
:initial value
所做的,但您能解释一下该语法的语义吗?它是
reduce
的可选关键字参数。通用Lisp函数可以采用命名参数,其中名称是Lisp符号。前导冒号只是符号的lisp语法。对于初始值,函数的第一次调用是使用
(initial value,element0)
,而不是
(element0,element1)
。现在我理解了代码,我更喜欢原始版本,因为它具有经典的LISP简洁性:)如果我去“Haskell for初学者课程”,那篇文章会有一些意义“漂亮的折叠式”帖子更容易理解。
mean[l_List]:=
    Fold[{First@#1+1,(#2 +#1[[2]](First@#1-1))/First@#1}&,{1,1},l][[2]]  

In[23]:= mean[{a,b,c}]
Out[23]= 1/3 (a+b+c)