Day4: [资料结构] Array —  阵列

https://ithelp.ithome.com.tw/upload/images/20210904/20128604yXojHnLUmG.jpg

Array是资料结构的一种,概念就像置物柜一样,每个柜子都可以存放资料并且都有自己的编号称为索引值index,Array为连续的记忆体位置,因此读取资料非常快速,只要透过 array[index]就可以拿到资料了,时间复杂度为O(1),不过如果需要新增或删除资料,就会有牵一发动全身的问题,假如删除了阵列的第一个资料,则後续的资料都需要向前递补,时间复杂度为O(n),n为阵列的长度,以下就来介绍阵列常用的方法。

https://ithelp.ithome.com.tw/upload/images/20210904/20128604NgXU8YoSlC.png
array的索引值是从0开始

宣告一个空阵列

let arr = []

//在建立阵列时就先赋值
let memberList = ['Tom', 'Jack', 'Alice'];

Array[index]

取得特定位置的值

memberList[0]; //'Tom'

Array.length

获取阵列的长度

memberList.length; //3

Array.pop()

移除阵列最後一个值,并回传移除的项目

memberList.pop(); // 'Alice'

Array.push(value)

在阵列的最後面新增一个值

memberList.push("Rose");

Array.shift()

移除阵列的第一个值,并回传移除的项目

memberList.shift();

Array.unshift(value)

在阵列的最前面新增一个值

memberList.unshift("Shane");

Array.indexOf(value)

寻找目标对象在阵列中的索引值,如果找不到的话就会回传-1

memberList.indexOf("Jack"); //1

Array.lastIndexOf(value)

取指定对象最後一个出现的索引值,如果找不到的话就会回传-1

let student = ['Tom', 'Marry', 'Waston', 'Tom']
let lastPosition = student.lastIndexOf('Tom')
console.log(lastPosition) // 3

Array.includes(value)

检查该阵列是否有这个值,有的话回传true,没有的话回传false

memberList.includes("Jack"); //true

Array.findIndex(value)

寻找目标对象在阵列中的索引值,如果找不到的话就会回传-1

let student = [{id:1, name:'Tom'},{id:2, name:'Marry'},{id:3, name:'Waston'},{id:4, name:'Tina'}]
let res = student.findIndex((item) => {
 return item.name == 'Marry'
})
console.log(res) //1

Array.slice(begin, end)

用来切割阵列,不会改变原阵列

  • begin:起始的index ,若为-1则代表从倒数第一个开始算
  • end:结束的index ,若不填则代表选取到阵列最後一个元素
let memberList = ['Tom', 'Jack', 'Alice', 'Zora', 'Mike'];
memberList.slice(0, 2); //["Tom", "Jack"]
console.log(memberList) //['Tom', 'Jack', 'Alice', 'Zora', 'Mike'];

//如果想要用slice做浅拷贝可以这样写
memberList.slice()

Array.splice(begin, deleteCount, addItem)

用来切割阵列,会回传切除的部位,当阵列经过splice的处理之後,原阵列也会跟着改变

  • begin:起始index 若为-1则代表从倒数第一个开始算
  • deleteCount:要删除的个数
  • addItem:要添加的元素
let memberList = ['Tom', 'Jack', 'Alice', 'Zora', 'Mike'];
memberList.splice(0, 2) //["Tom", "Jack"] //回传被切割出来的阵列
console.log(memberList) //["Alice", "Zora", "Mike"] // 原阵列被修改了

//带入第三个参数addItem
let memberList = ['Tom', 'Jack', 'Alice', 'Zora', 'Mike'];
memberList.splice(0, 2, 'Dan') //["Tom", "Jack"] //回传被切割出来的阵列
console.log(memberList) //["Dan", "Alice", "Zora", "Mike"]

Array.forEach(callback)

遍历阵列除了传统的for回圈之外,也可以使用forEach或是for of

//forEach
memberList.forEach((item, index, array) => {
  console.log(`name${item}`, `index${index}`);
});

//for of
for (let value of memberList) {
  console.log("name", value);
}

Array.map(callback)

类似工厂的概念,阵列的元素会被逐一加工,最後会回传一个处理过後阵列

let student = ['Tom', 'Marry', 'Waston', 'Petter']
let result = student.map(item => {
 return `**${item}**`
})
console.log(result) //['**Tom**', '**Marry**', '**Waston**', '**Petter**']

Array.filter(callback)

过滤符合条件想要筛选出来的对象,若没有则回传空阵列

let family =['Tom','Marry','Waston','Petter']
let res = family.filter(item => {
  return item.includes('o')//搜寻谁的名字里含有"o"的
})

console.log(res) //['Tom', 'Waston']

Array.find(callback)

面试很喜欢问find跟filter的差异,filter会回传一个阵列包含所有符合条件的对象,find则是只能回传第一个符合条件的对象,没有的话则return undefined

let family =['Tom','Marry','Waston','Petter']
let res = family.find(item => {
  return item.includes('o')//搜寻谁的名字里含有"o"的
})

console.log(res) //'Tom' 只回传第一个找到的

Array.every(callback)

检查阵列的每一个项目是否符合条件,只要有一个对象不符合就return false

let list = ['tea','soda','water']
let res = list.every(item => {
  return item.length == 3 //是否每个项目的长度都大於3
})
console.log(res) //false

Array.some(callback)

阵列中只要有一个对象符合条件,就return true

let list = ['tea','soda','water']
let res = list.some(item => {
  return item.length >= 5 //是否项目的长度大於5
})
console.log(res) //true

Array.sort(callback)

将阵列由小到大排序,字母的话按照a-z,如果没有带入callback function,就会将阵列每个项目转换成字串来比对,不过这里就会发现一个问题,为甚麽300会排在55的前面?因为以比对字串来说,300的「3」小於55的「5」,因此才会出现300比55还小的这种诡异情形。

let family =['Tom','Marry','Waston','Petter']
family.sort() //['Marry', 'Tom', 'Tom', 'Waston']

let num = [12,25,55,300]
num.sort() //[12, 25, 300, 55]

num.sort((prev, next) => next - prev);
console.log(num);  //[300, 55, 25, 12] 由大到小排列
num.sort((prev, next) => prev - next);
console.log(num);  //[12, 25, 55, 300] 由小到大排列

Array.reverse()

反转阵列的顺序

let member = ['Tom','Marry','Waston','Petter']
let res = member.reverse()
console.log(res) //['Petter', 'Waston', 'Marry', 'Tom']

Array.concat()

将多个阵列串联成同一个阵列

let teamA = ['Tom','Marry','Waston','Petter']
let teamB = ['Kevin','Joe','Vicky','Roy']
let teamAll = teamA.concat(teamB)
console.log(teamAll) 
//["Tom", "Marry", "Waston", "Petter", "Kevin", "Joe", "Vicky", "Roy"]

Array.reduce(callback)

将阵列的元素传入callback处理,最後阵列会化作单一值(引用MDN的说明)
array.reduce(callback(accumulator, currentValue, currentIndex, arr), initialValue)

  • accumulator:用来累积回呼函式回传值的累加器(accumulator)或 initialValue。累加器是上一次呼叫後,所回传的累加数值
  • currentValue:原阵列目前所迭代处理中的元素。
  • currentIndex (非必填):原阵列目前所迭代处理中的元素之索引。若有传入 initialValue,则由索引 0 之元素开始,若无则自索引值 1 之元素开始。
  • array(非必填):呼叫 reduce() 方法的阵列。
  • initialValue(非必填):於第一次呼叫 callback 时要传入的累加器初始值。若没有提供初始值,则原阵列的第一个元素将会被当作初始的累加器
let array = [1, 2, 3, 4];
let reducer = (accumulator, currentValue) => accumulator + currentValue;// 1 + 2 + 3 + 4
console.log(array.reduce(reducer));
// expected output: 10  // 5 + 1 + 2 + 3 + 4
console.log(array.reduce(reducer, 5));
// expected output: 15

因此用reduce来找阵列里面最大或是最小的数字也是很方便的

let array = [1, 2, 3, 4];
let res = array.reduce((accumulator, currentValue)=>{
  return Math.max(accumulator, currentValue)
})
console.log(res)
//output: 5

Array.reduceRight(callback)

跟reduce差不多,不过顺序变成由右至左,如果是做数字加总那结果是一样的,如果是组字串那就可以看得出差异

let array = ['a', 'b', 'c', 'd', 'e']; 
let left  = array.reduce((prev, cur)=>{ return prev + cur; }); 
let right = array.reduceRight((prev, cur)=> { return prev + cur; }); 

console.log(left);  // "abcde"
console.log(right); // "edcba"

Array.from(target)

可以将类阵列转换成阵列
Array.from(arrayLike, mapFn , this)

  • 类阵列(array-like)物件: 物件具有 length 属性以及索引化(indexed)的元素
  • mapFn(非必填) :可以传入map function来做进一步的处理
  • this(非必填): mapFn 函式执行时的 this 对象
Array.from('Hello')
 //output: ['H','e','l','l','o']

假如今天我想要建立一个数字1–99的阵列可以怎麽做?一个一个慢慢写当然是可以,只是写完可能就天黑了,使用Array from搭配map一行轻松搞定。

Array.from({length: 99}, (v, i) => i+1)

Array.flat()

函数以递回方式将特定深度的子阵列重新串接成为一新的阵列,会传入参数来指定巢状阵列展开的深度,没有传的话预设是1。

let arr1 = [1, 2, [3, 4]];
arr1.flat();  // [1, 2, 3, 4]
let arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(); // [1, 2, 3, 4, [5, 6]]
let arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // [1, 2, 3, 4, 5, 6]

Array.join()

将阵列里的项目组成字串,可指定间隔字串

let family =['Tom','Marry','Waston','Petter']
let str = family.join('!')
console.log(str) //"Tom!Marry!Waston!Petter"

Array.fill()

填满的概念,把大家通通变成指定的元素,会改变原本的阵列

let student = ['Tom','Marry','Waston','Tom']
var res = student.fill('shane')
console.log(res) 
//['shane', 'shane', 'shane', 'shane']

最後放上Tommy大大绘制的阵列操作大全,最常用阵列操作方法都列在上面了!
https://ithelp.ithome.com.tw/upload/images/20210904/20128604WFd4Ns5ICO.jpg
*图片来源:*https://github.com/tooto1985/js-array-operations


<<:  【Day4】Eslint设定及JSX表达式介绍,乾净整齐的程序码才能使人轻松读懂!(๑¯◡¯๑)

>>:  Golang 变数与型态

用React刻自己的投资Dashboard Day5 - 多张图表渲染(Rendering lists)

tags: 2021铁人赛 React 上一篇只画了一张图表,投资怎麽可能只需要看一张图呢?这边就再...

Day3 JavaScript 如何输出

JavaScript 可以通过不同的方式来输出数据: 1.使用 window.alert() 弹出警...

[DAY28]GKE-Google Kubernetes Engine

GKE GKE是GOOGLE在GCP上面的k8s cluster服务,对於GCP使用者来说,GKE可...

我虽是灾难吸引器-但真的没有发色情连结

常遇到灾难级的Crash...这次是更... 今早,7:54分上班,就开始在机房里作业,10点多的时...

Day14 - 【概念篇】OAuth flows: Implicit (Legacy)

本系列文之後也会置於个人网站 +----------+ | Resource | | Owner ...