js如何返回输入两个数值的乘积_一个关于JS解决数组相乘问题

数组相乘,顾名思义就是将多个数组的每一元素乘(组合)起来。它的结果以几何数级增长,初次遇到此类问题时,常常使人头皮发麻,我们现在以js的角度来解决这个问题。

从实例出发

众所周知,女孩出门前一般需要经过精心打扮,那么假设你有一个女朋友,她有着3顶帽子,5件衣服,5条裤子,3双鞋子,2只口红,4个包包,2副墨镜,且心情可能会影响穿着,她可能因为心情不好而选择不带一些物品,但是她会告诉你她会穿戴什么,要求列举所有方案,看到题目后……5fcca2139033af867c5e25136ef26137.png

不说了,先将实际问题转化成语言问题吧。

七个数组,分别表示七种穿戴,数组中存值为该穿戴的代号,传值为字符串是她告诉你她需要的穿着,例"clothes trousers",中间以空格隔开

const hat = ['a','b','c'];

const clothes = ['0','1','2','3','4'];

const trousers = ['q','w','e','r','t'];

const shoes = ['A','B','C'];

const lipstick = ['$1','$2'];

const bag = ['¥1','¥2','¥3','¥4'];

const sunglasses = ['^1','^2'];

function getComb(str){

return arr;

}

复制代码

解决思路

秉着不管什么问题,看到数组我就用循环的思路,去解题,难免会遇上很多问题。如果,题目上明确指出女朋友心情必须max每次出门都装备拉满,那ok没问题,7次循环解决。但是女人心海底针呐,你只能通过她告诉的穿着来列举(如果无论什么情况,你都用7次循环,那当我没说)。

随机数法

我们可以让电脑自己随机组合,并判断如果已经添加过这个结果,就不加进数组就ok了。

const arr = str.split(' ')

.map(name => {

switch (name) {

case 'hat': return hat;

case 'clothes': return clothes;

case 'trousers': return trousers;

case 'shoes': return shoes;

case 'lipstick': return lipstick;

case 'bag': return bag;

case 'sunglasses': return sunglasses;

}

})

复制代码

先将传入的字符串转化一个与它传值相关的二维数组,例:传入"hat clothes"

arr为[ [ 'a', 'b', 'c' ], [ '0', '1', '2', '3', '4' ] ],这样我们就得知了穿戴的数目,以及该穿戴的种类了。我们不难得出,这种情况下最多能列出15种结果,定义一个total变量并修改一下上面代码。

let total = 1;

const arr = str.split(' ')

.map(name => {

switch (name) {

case 'hat': total *= hat.length ; return hat;

case 'clothes': total *= clothes.length ; return clothes;

case 'trousers': total *= trousers.length ; return trousers;

case 'shoes': total *= shoes.length ; return shoes;

case 'lipstick': total *= lipstick.length ; return lipstick;

case 'bag': total *= bag.length ; return bag;

case 'sunglasses': total *= sunglasses.length ; return sunglasses;

}

})

复制代码

如果使用随机数我们就能将一个多次循环转化为一个while判断的for循环。我们new一个数组result,由于我们知道一共有几种结果,所以while循环的条件就是:result.length < total.

let result = [], sum = '';

while (result.length < total) {

for (let i = 0; i < arr.length; i++) {

sum += arr[i][parseInt(Math.random() * arr[i].length)];

}

if (result.indexOf(sum) == -1)

result.push(sum);

sum = '';

}

return result;

复制代码

注意:Math.random()是产生一个[0,1)的随机浮点数,数组的索引是整数,所以我们需要转换类型;sum是数组的组合,所以我们在添加完后需要了给它还原.

随机数法的缺点:

算法过于暴力,由于Math.random值返回的不确定性,导致很多时间会浪费在生成一个数组已经添加过的值上。

reduce方法

我们也可以使用reduce方法非常简便的完成数组的乘法.很多初学者可能会对reduce比较陌生,因为这是一个不常见的方法,但是使用reduce进行很方便,先简单介绍一下reduce方法。

reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值

reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

arr.reduce(callback,[initialValue])

callback (执行数组中每个值的函数,包含四个参数)

previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))

currentValue (数组中当前被处理的元素)

index (当前元素在数组中的索引)

array (调用 reduce 的数组)

initialValue (作为第一次调用 callback 的第一个参数。)

复制代码

基础用法

const a = [1,2,3,4,5,6];

const rst = a.reduce((pre,cur)=>{

return pre + cur;

})

console.log(rst); // rst = 1+2+3+4+5+6

复制代码

pre为第一个值或上次计算的结果,这里没有传初值,pre初始默认为0,cur为数组的每一个值。这里解析过程:

=> pre = 0 ; cur = a[0];

=> pre = 0 + a[0] ; cur = a[1];

=> pre = 0 + a[0] + a[1] ; cur = a[2];

...

rst = 0 + 1 + 2 + 3 + 4 + 5 + 6 // 21

复制代码

用reduce解决数组相乘

return arr.reduce((pre,cur)=>{

return [].concat(...pre.map(e=>cur.map(ele=>ele+e)))

})

复制代码

例:

str = 'clothes hat bag';

=> arr :

[ [ '0', '1', '2', '3', '4' ],

[ 'a', 'b', 'c' ],

[ '¥1', '¥2', '¥3', '¥4' ] ]

复制代码

首先将一个复杂组合问题,转化为叠加组合问题。如果能将arr[0],arr[1]两个组合的结果返回给pre,那么我们就能通过两两组合来完成复杂组合。接下来使用map完成两两组合:

pre : [ '0', '1', '2', '3', '4' ]

cur : [ 'a', 'b', 'c' ]

pre.map(e => cur.map(ele => e + ele));

/*第一次*/

e : '0' , ele: 'a' , e + ele ='0a', pre[['0a']]

e : '0' , ele: 'b' , e + ele = '0b', pre[['0a','0b']]

...

/*结束*/

pre[['0a','0b','0c'],['1a','1b','1c'],['2a','2b','2c'],['3a','3b','3c'],['4a','4b','4c' ]]

cur : [ '¥1', '¥2', '¥3', '¥4' ]

复制代码

接下来我们只需要将二维数组pre转化为一维数组,然后函数就会随着reduce一步一步将数组相乘起来了

[].concat[...pre.map(e => cur.map(ele => e + ele))]

复制代码

扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,一般在传参时使用。

到这里我们就解决这个女朋友出门的问题了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值