是否有一个函数可以让我连接多个数组,它们之间有分隔符(分隔符也是数组),类似于join
的工作原理但不限于字符串?
该函数可以是标准JS或主要库的一部分,例如lodash
(这就是它在标签中被引用的原因)。
以下是一个使用示例:
let numbers = [[1], [2], [3]];
let result = _.joinArrays(numbers, [0]);
console.log(result);
//printed: [1, 0, 2, 0, 3]
这类似于:
let strings = ["a", "b", "c"];
let result = strings.join(",");
console.log(result);
//printed: "a,b,c";
但是,join
无法使用,因为它会将值转换为字符串,我不想发生这种情况。
但它适用于任何类型。
答案 0 :(得分:8)
您可以简单地使用<a href="" onclick="window.history.go(-1); return false;">back</a>
来连接数组,并推送您想要用作分隔符的内容。
array.reduce
答案 1 :(得分:3)
这里是完整的monty。发疯。
var numbers = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
],
delimiters = [
',', '-', 'x'
];
// matrix interspersion, delimiters into numbers's children
// the rank/order/whatevs of the matrix can be arbitrary and variable
numbers.forEach((x, i) => {
for (var j = 1, l = x.length; j <= l; j+=2 )
x.splice(j, 0, delimiters[i]);
})
alert( "Matrix interspersed: " + JSON.stringify(numbers) );
// normal interspersion, a static delimiter into numbers
for (var j = 1, l = numbers.length; j <= l; j+=2 )
numbers.splice(j, 0, ' AND ');
alert( "Outer array interspersed: " + JSON.stringify(numbers) );
// flattening a 2 rank array into a single array
var flattened = Array.prototype.concat.apply([], numbers);
alert( "Flattened: " + JSON.stringify(flattened) );
&#13;
答案 2 :(得分:0)
var result = [].concat.apply([], numbers);
console.log(result)
答案 3 :(得分:0)
如果需要,您可以使用Array#reduce
并返回包含项目和粘合的数组。
const join = (array, glue) => array.reduce((a, b) => a.concat(glue, b));
var numbers = [[1], [2], [3]];
console.log(join(numbers, [0]));
console.log(join(numbers, [42, 43]));
console.log(join([[1]], [0]));
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
答案 4 :(得分:0)
这是一个执行此功能的函数的实现,带有一些额外的逻辑,以防其他人想要这样做。我真的在问这是否已经存在。
需要lodash。
export function intersperse(arrs, delimeter) {
let joined = [];
for (var i = 0; i < arrs.length; i++) {
let arr = arrs[i];
if (!arr) continue; //handle sparse arrays
joined.push(...arr);
if (i === arrs.length - 1) break;
if (_.isFunction(delimeter)) {
joined.push(...delimeter());
} else if (_.isArray(delimeter)) {
joined.push(...delimeter);
} else {
throw new Error("unknown type");
}
}
return joined;
}
答案 5 :(得分:0)
这里有许多好的答案,包括4Castle的评论。至于改变,我想为这项工作开发一个通用的Array.prototype.intersperse()
。
在功能性JS中,我可以为这项工作提出3种选择;
Array.prototype.intersperse_1 = function(s){
return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s));
};
Array.prototype.intersperse_2 = function(s){
return this.reduce((p,c,i) => (i ? p.push(s,c) : p.push(c),p),[]);
};
Array.prototype.intersperse_3 = function(s){
return this.reduce((p,c,i) => i ? p.concat([s],[c]) : p.concat([c]),[]);
};
你应该远离第三个,因为.concat()
是功能JS中最昂贵的操作之一。它甚至无法完成100K项目的工作。
另一方面,虽然在小尺寸阵列中总是稍微快一点,但在FF和Chrome中,第一个在非常大的阵列中比第二个快2倍甚至更快。即,第一次在不到1000毫秒内散布一个10M物品阵列,而对于相同的工作,第二次在2000-2500毫秒内散布。当然,处理这个大小是不可能的。
因此在这种特殊情况下,与定制解决方案相比,它可能会更昂贵,因为我们必须将结果映射到原始值,但我想仍然值得注意以下代码。我确信当阵列长度超过某个数字时,.concat()
采用量身定制的解决方案将落后于此。
Array.prototype.intersperse = function(s){
return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s));
}
var arr = [[1],[2],[3]],
result = arr.intersperse([0])
.map(e => e[0]);
console.log(JSON.stringify(result));
答案 6 :(得分:0)
如前所述,最简单的方法是
function intercalate(glue, arr){
return arr.reduce((acc, v) => acc.concat(glue, v));
}
但这不是最好的方法,因为它会在每次迭代时创建一个新的(中间)数组,然后抛弃它。这对于这个短的数组值无关紧要,但是如果您打算在更长的数组上使用它,您可能会注意到这种影响。
最好是创建一个数组并将值推入其中,因为它们会进入。
function intercalate(glue, arr){
const push = (acc, v) => (Array.isArray(v)? acc.push(...v): acc.push(v), acc);
return arr.reduce((acc, v, i) => push(i===0? acc: push(acc, glue), v), []);
}
但是由于这个数据逐渐增加,它可能仍然需要分配更大的内存块并复制数据。这些任务非常高效,但仍然没有必要(imo);我们可以做得更好。
我们首先创建一个包含所有数组和中间分隔符的列表,然后使用concat.apply([], list)
将其展平。因此,我们生成一个中间数组,我们可以提前计算其大小,其余的是Array.concat的问题,它是底层实现。
function intersperse(delimiter, arr){
if(!arr.length) return [];
let j = 0, push = (acc, v) => (acc[j++] = v, acc);
return arr.reduce((acc, v) => push(j===0? acc: push(delimiter, glue), v), Array(2*arr.length-1));
}
//or
function intersperse(delimiter, arr){
if(!arr.length) return [];
var out = Array(2*arr.length-1);
out[0] = arr[0];
for(var i=1, j=1; j<out.length;){
out[j++] = delimiter;
out[j++] = arr[i++];
}
return out;
}
//and
function intercalate(glue, arr){
var emptyArray = [];
return arr.length?
emptyArray.concat.apply(emptyArray, intersperse(glue, arr)):
emptyArray;
}
Wich版本将是最好/最快的,最后,并不容易分辨,因为它可能取决于传递的值,而JIT编译器是否优化了它的s ***。我提出了我的观点,由你来选择你使用的版本/实现。
对于第一个版本:您可能更愿意不将它放入lib中,但是主要将其写入内联(它简短且足够简单),因此JIT编译器可能不会尝试在不同的调用(#monomorphic function / code)之间找到一些常见类型,从而单独优化每个出现。另一方面,这可能是过早优化。这取决于你。