请教用 JavaScript 计算这个东西的方法

2018-03-12 18:12:39 +08:00
 70599
假设我有一个数组:
[11,21,34,65,14,5,66,17,88,21,45,61,50]

我想要算出这个数组中每个值(包含它自己)之后 10 个值的整数平均值,并输出到一个数组。
当后面的值不到 10 个的时候,就算出它自己到最后 1 个值的平均值。

觉得是一个简单的事情,可是想了好久一筹莫展,请大家帮忙。
5327 次点击
所在节点    JavaScript
41 条回复
zouyyu
2018-03-12 18:18:50 +08:00
array 有个 slice 方法截取数组 数组循环的时候能取到当前元素索引 。然后递归就可以了
rrfeng
2018-03-12 18:20:13 +08:00
循环一遍不就行了...有啥好计算的
grantonzhuang
2018-03-12 18:20:16 +08:00
reduce 了解一下
mskf
2018-03-12 18:25:40 +08:00
lodash 了解一下

_.chain([11,21,34,65,14,5,66,17,88,21,45,61,50] ).chunk(10).map((arr)=>{return _.sum(arr)/arr.length}).value()
Building
2018-03-12 18:27:35 +08:00
怎么会没思路呢,多简单啊,就像这样:

if( arr.length === 0 ) return []

if( arr.length === 1 ) return arr

if( arr.length === 2 )
var res = []
res[0] = (arr[0] + arr[1]) / 2
res[1] = (arr[1])
return res

if( arr.length === 3 )
......
SuperMild
2018-03-12 18:33:46 +08:00
授人以渔。

通过编程来解决问题,一个关键的技巧是把大问题分解为小问题!

比如这个问题,可以这样分解:

首先,取第一组 10 个数,把这 10 个数 print 出来。

然后,取下一组 10 个数,print 出来。(做完这两个小实验,就证明会用 slice 了)

然后,写一个循环,把每一组 10 个数都 print 出来。(做完这步,就证明会用循环了)

然后,把上一步那个循环改一下,不 print 10 个数,而是 print 它们的平均值。(这个小改动不难)

然后,思考一下怎样把这些平均值塞进一个数组里。

这就完成了。注意,每一步都不是很难,难的是初学者不习惯这种把大问题分解为小问题的思考方法。
rabbbit
2018-03-12 18:38:28 +08:00
[0,1,2,3,4,5,6,7,8,9,10,11,12].map((num, i, arr) =>{return arr.slice(i, i + 11).reduce((x, y)=>{return (x + y) / 11})})
zohan
2018-03-12 18:40:50 +08:00
reduce +1
lambdaxs
2018-03-12 18:43:11 +08:00
输入数组为 a,输出数组为 b
a 数组中的每一个元素都可以通过一个映射关系转化为 b 数组中对应的元素
所以确定可以使用 Array.map 函数,然后来写 map 中的 f
f 为向后取最大 10 个元素累加求平均的函数
先实现 f,再把 f 扔到 map 里
work~~
rabbbit
2018-03-12 18:49:08 +08:00
唔,好像写错了
[0,1,2,3,4,5,6,7,8,9,10,11,12].map((num, i, arr) =>{return arr.slice(i, i + 11).reduce((x, y, i, arr)=>{return (x + y) / arr.length})})
rabbbit
2018-03-12 18:56:04 +08:00
上边那个还是不对...
算了不管了
[0,1,2,3,4,5,6,7,8,9,10,11,12].map((num, i, arr) =>{return arr.slice(i, i + 11).reduce((x, y)=>{return x + y}) / arr.slice(i, i + 11).length})
ipwx
2018-03-12 19:26:38 +08:00
@rabbbit 我看你写了三遍,可是全都是 O(10N) 的。应该写 O(N) 的算法。
ipwx
2018-03-12 19:27:13 +08:00
@rabbbit 抱歉,O(N) 应该到不了,O(2N) 应该行。
ipwx
2018-03-12 19:36:18 +08:00
@70599 少年,如果你不会“优雅的写法”,为什么不一步一个脚印,用最基础的写法写呢?反正有 V8 的 JIT,用累加器和循环并不慢啊。比如 https://gist.github.com/korepwx/2c4c63741fed0effdd70f3bf80070530

再说这个写法其实比上面 @Building @rabbbit 高效才对。因为他们是 O(10N),而这个写法是 O(2N)。
ipwx
2018-03-12 19:41:30 +08:00
@70599 好吧,我上面的代码可能理解错了题意。不过应该很好改才对,你也可以试试。
lightening
2018-03-12 20:21:34 +08:00
@ipwx o(10n) 和 o(2n) 都是 o(n) 。
lightening
2018-03-12 20:34:23 +08:00
怎么会想不出来呢?我就不说聪明的方法了,只说最容易想的笨办法,主要是提供一个解决问题的思路:

我们要把原数组的每个元素映射到另一个元素,那么:

array.map((element, index) => {
doSomethingToEachElement(...)
})

每个元素做点什么呢?根据你说的
> 我想要算出这个数组中每个值(包含它自己)之后 10 个值的整数平均值,并输出到一个数组。
> 当后面的值不到 10 个的时候,就算出它自己到最后 1 个值的平均值。

function doSomethingToEachElement() {
if (remaining.length >= 10) {
return average( firstTenOf(remaining) )
} else {
return average(remaining)
}
}

看一看上述代码,remaining 不知道,average 函数没写。那就补出来。这不用教吧?

你看很简单,每一行代码都是和你的描述的对应的。把缺的参数补齐,缺的变量怎么计算填上,不就写出来了?
如果一个问题你没有思路,就根据中文描述,一一对应的先写出来。写出来后,然后再看有没有办法简化。
qfdk
2018-03-12 20:40:40 +08:00
简单的问题为啥这么复杂 取 0-9 是个数 算平均 然后 pop 掉第一个数 再取十个 递归就好了 终止条件就是数组长度不为 10
qppq54s
2018-03-12 20:44:57 +08:00
let a = [11,21,34,65,14,5,66,17,88,21,45,61,50] ;
let b = a.length;
for(let i = 0; i< 10; i++) {a.push(0)};
let result = [];
for (let i = 0;i < b; i++) {
result.push( (a[i] + a[i+1] + a[i+2] + a[i+3] + a[i+4] + a[i+5] + a[i+6] + a[i+7] + a[i+8] + a[i+9])/10);
}
AlisaDestiny
2018-03-12 20:53:29 +08:00
```javascript
var arr = [11,21,34,65,14,5,66,17,88,21,45,61,50];
var sum = 0;
for(var i=0;i<10 && i<arr.length;i++){
sum += arr[i];
}
while(arr.length > 0){
var avg = sum / Math.min(arr.length,10);
console.log("avg:" + avg);
if(arr.length>10){
sum += arr[10];
}
sum -= arr.shift();
}
```
复杂度:O(n)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/437360

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX