请教数组内的数组元素如何合并?

如下:

let arr = [[], [1,2,3], [4,5,6], [7]];

怎么合成[1,2,3,4,5,6,7]呢?

阅读 4.7k
8 个回答

一、reduce

var total = [0,1,2,3,4].reduce((a, b)=>a + b); //10
reduce接受一个函数,函数有四个参数,分别是:
  • 1、上一次的值;
  • 2、当前值;
  • 3、当前值的索引;
  • 4、数组;
我们还是以上面那个数组为例,把这几个参数打印出来看看:
[0, 1, 2, 3,4].reduce(function(previousValue, currentValue, index, array){
 return previousValue + currentValue;
});
reduce 还可以扁平化一个二维数组
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
 return a.concat(b);
}, []);
// flattened == [0, 1, 2, 3, 4, 5]

二、splice

splice()
方法向/从数组中添加/删除项目,然后返回被删除的项目
[1,2,3,4,5].splice(2,0,9);
//[1,2,9,3,4,5]
[1,2,3,4,5].splice(2,2,9);
//[1,2,9,5]

三、concat

在现有数组后面追加数组,并返回新数组,不影响现有数组。
var arra = [1,2,3];
var arrb = [4,5,6];
var arrc = arra.concat(arrb);
//[1, 2, 3, 4, 5, 6]

四、join

用指定间隔符连起来,把数组转为字符串。
var arrstr = ['a','b','c','d','e','f','g'];
arrstr.join("*");
///"a*b*c*d*e*f*g"
但需要注意的是只转换一维数组里面,如果数组里面还有数组,将不是采用join指定的字符串接,而是采用默认的toString();
var a = ['a','b','c','d','e','f','g',[11,22,33]];
a.join("*");  
// -> a * b * c * d * e * f * g *    11,22,33

五、pop shift unshift

1.pop:删除数组最后一个元素,并返回该元素

var a = ["aa","bb","cc"];
a.pop();  //cc

2.shift:删除数组第一个元素,并返回该元素

var a = ["aa","bb","cc"];
a.shift();   
// -> aa
a
// -> bb,cc

==注:当数组为空时,返回undefined==

3.unshift:跟shift相反,往数组最前面添加元素,并返回数组新长度。

var a = ["aa","bb","cc"];
a.unshift();
//4 注:IE下返回undefined

六、sort reverse

1.sort: ANSI碼正序;

var a = [11,2,3,33445,5654,654,"asd","b"];
a.sort() // -> 11,2,3,33445,5654,654,asd,b

2.reverse :ANSI碼倒序;

var a = [11,3,5,66,4];
a.reverse();  
// -> 4,66,5,3,11
==如果数组里面还包含数组,则当为对象处理,并不会把元素解出来==
var a = ['a','b','c','d','e','f','g',[4,11,33]];
a.reverse(); 
// -> 4,11,33,g,f,e,d,c,b,a
a.join(" * "); 
// -> 4,11,33 * g * f * e * d * c * b * a

七、slice splice

1.slice:返回数组片段

var a = ['a','b','c','d','e','f','g'];
alert(a.slice(1,2));  // -> b
alert(a.slice(2));    // -> c,d,e,f,g
alert(a.slice(-4));   // -> d,e,f,g
alert(a.slice(-2,-6));    // -> 空

2.splice:从数组删除某片段的元素,并返回删除的元素

var a = [1,2,3,4,5,6,7,8,9];
document.write(a.splice(3,2));    // -> 4,5
document.write(a);        // -> 1,2,3,6,7,8,9
document.write(a.splice(4));  // -> 7,8,9 注:IE下返回空
document.write(a);        // -> 1,2,3,6
document.write(a.splice(0,1));    // -> 1
document.write(a);        // -> 2,3,6
document.write(a.splice(1,1,["aa","bb","cc"]));   // -> 3
document.write(a);        // -> 2,aa,bb,cc,6,7,8,9
document.write(a.splice(1,2,"ee").join("#")); // -> aa,bb,cc#6
document.write(a);        // -> 2,ee,7,8,9
document.write(a.splice(1,2,"cc","aa","tt").join("#"));  // -> ee#7
document.write(a);        // -> 2,cc,aa,tt,8,9
==注:注意该方法在IE下,第二个参数是必须的,不填则默认为0,例如a.splice(4),在IE下则返回空,效果等同于a.splice(4,0)==

八、toString toLocaleString valueOf

1.toString:把数组转为字符串,不只数组,所有对象均可使用该方法

var a = [1,2,[3,4],5];
a.toString();
//1,2,3,4,5

var b = 10;
b.toString(2);
// 1010   2进制转换

var a =    [5,6,7,8,9,["A","BB"],100];
document.write(a.toString());    // -> 5,6,7,8,9,A,BB,100
var b = new Date()
document.write(b.toString());    // -> Sat Aug 8 17:08:32 UTC+0800    2009
var c = function(s){
alert(s);
}
document.write(c.toString());    // -> function(s){ alert(s); }
布尔值则返回true或false,对象则返回[object objectname]
相比join()方法,join()只对一维数组进行替换,而toString()则把整个数组(不管一维还是多维)完全平面化
同时该方法可用于10进制、2进制、8进制、16进制转换,例如:
var a =  [5,6,7,8,9,"A","BB",100];
for(var i=0; i<a.length; i++){
document.write(a[i].toString()    + " 的二进制是 "    + a[i].toString(2) + " ,八进制是 " + a[i].toString(8) + " ,十六进制是 " + a[i].toString(16));  //    -> 4,5
}
/**
5 的二进制是 101 ,八进制是 5 ,十六进制是 5
6 的二进制是 110 ,八进制是 6 ,十六进制是 6
7 的二进制是 111 ,八进制是 7 ,十六进制是 7
8 的二进制是 1000 ,八进制是 10 ,十六进制是 8
9 的二进制是 1001 ,八进制是 11 ,十六进制是 9
A 的二进制是 A ,八进制是 A ,十六进制是 A
BB 的二进制是 BB ,八进制是 BB ,十六进制是 BB
100 的二进制是 1100100 ,八进制是 144 ,十六进制是 64
*/
==注:转换只能在元素进行,如果对整个数组进行转换,则原封不动返回该数组==

2.toLocaleString:返回本地格式字符串,主要用在Date对象上

var a = new Date();
document.write(a.toString());    // -> Sat Aug 8 17:28:36 UTC+0800    2009
document.write(a.toLocaleString());   // -> 2009年8月8日 17:28:36
document.write(a.toLocaleDateString());   // -> 2009年8月8日

区别在于,toString()返回标准格式,toLocaleString()返回本地格式完整日期(在【控制面板】>>【区域和语言选项】,通过修改[时间]和[长日期]格式),toLocaleDateString()跟toLocaleString()一样,只是少了时间

3.valueOf:根据不同对象返回不同原始值,用于输出的话跟toString()差不多,但是toString()是返回string类型,而valueOf()是返回原对象类型

var a = [1,2,3,[4,5,6,[7,8,9]]];
var b = new Date();
var c = true;
var d = function(){
alert("sunnycat");
};
document.write(a.valueOf());    // -> 1,2,3,4,5,6,7,8,9
document.write(typeof (a.valueOf()));  // -> object
document.write(b.valueOf());    // -> 1249874470052
document.write(typeof(b.valueOf()));  // -> number
document.write(c.valueOf());    // -> true
document.write(typeof(c.valueOf()));  // -> boolean
document.write(d.valueOf());    // -> function () {    alert("sunnycat"); }
document.write(typeof(d.valueOf()));  // -> function
数组也是对象,所以typeof (a.valueOf())返回object,返回的依然是个多维数组
var a = [1,2,3,[4,5,6,[7,8,9]]];
var aa = a.valueOf();
document.write(aa[3][3][1]); // -> 8
==注:Date对象返回的是距离1970年1月1日的毫秒数,Math和Error对象没有valueOf方法==

九、every() filter() find() some() includes()

1.every

array.every(function(currentValue,index,arr), thisValue)
  • currentValue 必须。当前元素的值
  • index 可选。当期元素的索引值
  • arr 可选。当期元素属于的数组对象

  • every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
  • every() 方法使用指定函数检测数组中的所有元素:
如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
如果所有元素都满足条件,则返回 true。
  • 注意: every() 不会对空数组进行检测。
  • 注意: every() 不会改变原始数组。
var a = [1,2,3,4,5];
function checkAdult(num){
    return num > 0
}
a.every(checkAdult);
//true
/**
array.every(function(currentValue,index,arr), thisValue)
currentValue    必须。当前元素的值
index            可选。当期元素的索引值
arr                可选。当期元素属于的数组对象
*/

2.filter

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。

  • 注意: filter() 不会对空数组进行检测。
  • 注意: filter() 不会改变原始数组。
ar ages = [32, 33, 16, 40];

function checkAdult(age) {
    return age >= 18;
}

function myFunction() {
    document.getElementById("demo").innerHTML = ages.filter(checkAdult);
}
//32,33,40

3.find

array.find(function(currentValue, index, arr),thisValue)

find() 方法返回传入一个测试条件(函数)符合条件的数组第一个元素。
find() 方法为数组中的每个元素都调用一次函数执行:
当数组中的元素在测试条件时返回 true 时, find() 返回符合条件的元素,之后的值不会再调用执行函数。
如果没有符合条件的元素返回 undefined

  • 注意: find() 对于空数组,函数是不会执行的。
  • 注意: find() 并没有改变数组的原始值。
var ages = [3, 10, 18, 20];
 
function checkAdult(age) {
    return age >= 18;
}
 
function myFunction() {
    document.getElementById("demo").innerHTML = ages.find(checkAdult);
}
//18

4.some

array.some(function(currentValue,index,arr),thisValue)
  • some() 方法用于检测数组中的元素是否满足指定条件(函数提供)
  • 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。

5.includes

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。ES2016 引入了该方法。
  • indexOf方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN的误判。[NaN].indexOf(NaN)

// -1

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true
下面代码用来检查当前环境是否支持该方法,如果不支持,部署一个简易的替代版本。
const contains = (() =>
  Array.prototype.includes
    ? (arr, value) => arr.includes(value)
    : (arr, value) => arr.some(el => el === value)
)();
contains(['foo', 'bar'], 'baz'); // => false
另外,Map 和 Set 数据结构有一个has方法,需要注意与includes区分。
  • Map 结构的has方法,是用来查找键名的,比如Map.prototype.has(key)、WeakMap.prototype.has(key)、Reflect.has(target, propertyKey)。
  • Set 结构的has方法,是用来查找值的,比如Set.prototype.has(value)、WeakSet.prototype.has(value)。

十、fill

array.fill(value, start, end)
  • fill() 方法用于将一个固定值替换数组的元素
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.fill("Runoob");
//Runoob,Runoob,Runoob,Runoob

十一、entries() keys() values()

ES6 提供三个新的方法——entries(),keys()和values()——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历。
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

十二、Array.from()

类数组对象转数组
let arrayLike = {
  '0': 'a',
  '1': 'b',
  '2': 'c',
  length: 3
};

// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];

十三、Array.of()

  • Array.of方法用于将一组值,转换为数组
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

//模拟实现
function ArrayOf(){
  return [].slice.call(arguments);
}
arr.reduce((a, b) => a.concat(b))
//[1, 2, 3, 4, 5, 6, 7]

如果数组是多层的,用递归。代码:

function flatten(arr){
    return arr.reduce(
          function(prev, cur){
             return prev.concat(Array.isArray(cur) ? flatten(cur) : cur ); 
             // prev should be an array, if cur is not an array, we can concat it, otherwise, we should use iteration here. 
          }, []) // [] is the initial value for cur, since we want to use Array.prototype.concat, so here we should give an empty array as initial value.
}
let arr = [[], [1,2,3], [4,5,6], [7]];
let flatArray = [];
arr.forEach((item,index)=>{
    flatArray = flatArray.concat(item);
});
let arr = [[], [1,2,3], [4,5,6], [7]];
let newArr = [];
arr.forEach(v=>newArr = newArr.concat(v))
console.log(newArr)
function flattenArray(arr: Array<any>): Array<any> {
   let tempArr: Array<any> = [];
   for (let subarr of arr) {
     tempArr.push(...subarr);
   }
   return tempArr;
}

如果明确只有2层还比较好,如果不确定有多少层,就可能需要递归算法了。

扁平化两层数组:[].concat(...arr) 这就是最简单的了,没有比这更简单的。

扁平化多层数字数组:arr.toString().split(',').map(x=>+x)

扁平化多层数组:JSON.parse('[' + JSON.stringify(arr).replace(/[|]/, '') + ']') 这个不完美,你要想简单就去找lodash等第三方库

数组去重:[...new Set(arr)] 这就是最简单的了,没有比这更简单的。

手机党,纯手打

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题