use case1:
Input:['aa','bb','cc'],['dd','ee']
Output:["aadd", "aaee", "bbdd", "bbee", "ccdd", "ccee"]
use case2:
Input:['aa','bb','cc'],['dd','ee'],['ff','gg','hh']
Output:["aaddff", "aaddgg", "aaddhh", "aaeeff", "aaeegg", "aaeehh", "bbddff", "bbddgg", "bbddhh", "bbeeff", "bbeegg", "bbeehh", "ccddff", "ccddgg", "ccddhh", "cceeff", "cceegg", "cceehh"]
输入参数不定
方式 1 大概 250 - 300ms:
var mergeArr = (...args) => {
const mergeString = (a,b) => {
var s = '';
for (var i = 0 , len = b.length; i < len; i++){
if(i !== 0) s += ',';
s += a.join(b[i] + ',') + b[i];
}
var arr = s.split(',');
return arr;
}
var arrs = Array.apply(null, args);
var arrData = arrs[0];
for (var i = 1,len = arrs.length ; i < len; i++)
arrData = mergeString(arrData,arrs[i]);
// console.log(arrData);
};
方式 2 180 - 250 ms
function all() {
var pro = ''
for (var i = 0; i < arguments.length; i++) {
var obj = JSON.stringify(arguments[i]);
if(i !== arguments.length-1){
pro = pro + `
var outArr = []
function p${i}(str) {
for (var i = 0; i < ${obj}.length; i++) {
var obj = str + ${obj}[i];
p${i+1}(obj)
}
};`
}else{
pro = pro + `
function p${i}(str) {
for (var i = 0; i < ${obj}.length; i++) {
var obj = str + ${obj}[i];
outArr.push(obj)
}
};
p0('')
console.log(outArr)
`
eval(pro)
}
}
}
测试数据:
var time = new Date().getTime();
// mergeArr(['aa','bb','cc'],['dd'],['ee','ff']);
mergeArr(['aa','bb','cc'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh']);
console.log(new Date().getTime() - time);
还有更好的办法吗?
@shiyouming91
function mergeArr() {
var output = [];
doMerge(arguments, 0, "", output);
return output;
}
function doMerge(data, depth, prev, output) {
if(depth == data.length) {
output.push(prev);
} else {
let curr = data[depth];
for (let i = 0; i < curr.length; i++) {
doMerge(data, depth + 1, prev + curr[i], output);
}
}
}
var time = new Date().getTime();
mergeArr(['aa','bb','cc'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh']);
console.log(new Date().getTime() - time);
这个真的快,不用情况浏览器调试缓存,最快99ms
1
yemenchun1 2018-06-09 11:09:14 +08:00 via iPhone
js 不懂,但理论上,从后往前生成中间结果,保存成表,如 case2 的 ddff,ddgg,ddhh,再用第一个 array 中的元素连接它,可以节约一些时间。
|
2
notreami 2018-06-09 11:29:43 +08:00
难道我感觉错误,这才几个值,超过 50ms,都觉得奇怪
|
4
Chingim 2018-06-09 11:40:26 +08:00
题目链接发一下?不然很难评估提出来的方案的耗时
|
7
misaka19000 2018-06-09 11:45:08 +08:00
这不是算矩阵的乘积嘛
|
8
hoythan OP @misaka19000 有更好的思路吗通过 js
|
9
whileFalse 2018-06-09 11:51:05 +08:00
有啊,使用代理,也就是不实际生成数组。
|
10
hoythan OP @whileFalse 大哥给个路子?
|
11
jatai 2018-06-09 12:23:10 +08:00 via Android
用系统内置函数 forEach 就比自己写 for 快不少,教程上是这么说的 😄
|
12
lonhongg 2018-06-09 12:55:04 +08:00 1
顺手写了个 望赐教.
``` function fn(...arr) { let x = arr const res = [] x[0].map(i => { x[1].map(j => { res.push(i+j) }) }) if (x.length > 2) { x = x.splice(2) return fn(res, ...x) } else { return res } } fn(['a','b'],['A','B'],['x','y'],[1,2]) // ["aAx1", "aAx2", "aAy1", "aAy2", "aBx1", "aBx2", "aBy1", "aBy2", "bAx1", "bAx2", "bAy1", "bAy2", "bBx1", "bBx2", "bBy1", "bBy2"] ``` |
13
lonhongg 2018-06-09 13:01:52 +08:00
接上条 不会贴代码-,-
思路是每次取参数的前两个数组进行 map 后生成 res,比如[1,2][3,4][5,6] 第一次 res=[13,14,23,24] 然后用这个 res 和剩下的参数[5,6]进行递归,最终参数 length 不大于 2 后返回 res |
15
shiyouming91 2018-06-09 13:19:56 +08:00 1
function mergeArr() {
var output = []; doMerge(arguments, 0, "", output); return output; } function doMerge(data, depth, prev, output) { if(depth == data.length) { output.push(prev); } else { let curr = data[depth]; for (let i = 0; i < curr.length; i++) { doMerge(data, depth + 1, prev + curr[i], output); } } } 经典递归实现,在我的电脑上大概 120-150ms |
16
hoythan OP @jatai 循环中效率最高的应该是 for(var i = 0,len = arr.length; i < len; i++) 别人的测试结果
|
17
hoythan OP |
18
billgreen1 2018-06-09 14:05:20 +08:00
~~~javascript
function product() { var args = Array.prototype.slice.call(arguments); // makes array from arguments return args.reduce(function tl (accumulator, value) { var tmp = []; accumulator.forEach(function (a0) { value.forEach(function (a1) { tmp.push(a0.concat(a1)); }); }); return tmp; }, [[]]); } console.log(product([1], [2, 3], ['a', 'b'])); ~~~ |
19
hoythan OP @billgreen1 400-600ms
|
20
xiangyuecn 2018-06-09 14:21:49 +08:00
```
function run(list){ var rtv=[""]; for(var i=0;i<list.length;i++){ rtv=create(list[i],rtv); }; return rtv; }; function create(list,src){ var rtv=[]; for(var i=0,l1=src.length,l2=list.length;i<l1;i++){ for(var j=0;j<l2;j++){ rtv.push(src[i]+list[j]); }; }; return rtv; }; console.time(1); console.log(run([['aa','bb','cc'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh'],['ff','gg','hh'],['dd','ee'],['ff','gg','hh']]).length); console.timeEnd(1); ``` 非递归,第一次写了两个函数 测试 chrome41 古董首次执行 150ms,第二次以后 70-92ms chrome55 首次 109ms,第二次以后 50-60ms 不知道为什么第一次运行会慢一倍,编译吗? ------------ 第二次把第二个函数去掉了,其实没有必要要第二个函数,发现比第一次写的慢一点,chrome 内核的执行方式完全不符合可想而知的常理(滑稽 |
21
hoythan OP @xiangyuecn chrome 调试工具自带数据结果缓存的。
|
22
hoythan OP @xiangyuecn 我这边跑起来 150 - 200 左右
|
23
xiangyuecn 2018-06-09 14:29:56 +08:00
@hoythan 原来如此,怪不得以前测试速度经常飘来飘去,我去耍耍研究一下
|
24
glacer 2018-06-09 15:24:42 +08:00
笛卡尔积,MySQL 的 Nested Loop Join 了解一下
|
25
whileFalse 2018-06-09 15:35:49 +08:00 1
|
26
baelish 2018-06-09 15:37:03 +08:00
```javascript
function mergeArr(...args) { return args.reduceRight((sum, items, i)=>{ let tt = []; items.forEach(a=>{ sum.forEach(b=>{ tt.push(a+""+b); }) }) return tt; }, [""]); } ``` |
27
RqPS6rhmP3Nyn3Tm 2018-06-09 15:41:17 +08:00 via iPad
用 C 的指针写,然后上 WebAssembly
|
28
Exin 2018-06-09 15:44:18 +08:00
我来一个简短好读一点的:
```js function mergeArr(...groups) { const results = [] ~(function merge(prefix, nextGroup, ...groups) { if (nextGroup) nextGroup.forEach(word => merge(prefix + word, ...groups)) else results.push(prefix) })('', ...groups) return results } ``` 性能比楼主 append 的那一版略低一点点,但如果把 forEach 换成 for 就几乎一样了 |
29
yichinzhu 2018-06-09 15:59:54 +08:00 1
|