[JS] 7. Array




1. Array

  • 여러 개체(Entity)값을 순차적으로 나열한 자료 구조 (알고리즘 내 사용 빈도 up)
  • 배열 내 값을 요소(element)라고 하며, 배열 요소는 index로 접근
  • 대표 속성(property)과 메서드(method)
  • 배열 크기 및 배열 여부 확인 : Array.length, Array.isArray()
  • 배열 추가/삭제 : Array.push(), Array.pop(), Array.shift(), Array.unshift(), Array.splice(), Array.slice()
  • 배열 탐색 : Array.indexOf(), Array.lastIndexOf(), Array.includes()
  • 배열 변형(callback 미사용) : Array.sort(), Array.reverse(), Array.join()


배열 선언/접근/속성

let arr1 = new Array(10)
let arr2 = []

console.log(arr1) //[ <10 empty items> ]
console.log(arr2) //[]

let fruits = ["apple", "banana", "melon"]
console.log(fruits) //[ 'apple', 'banana', 'melon' ]

console.log(fruits[2]) //melon
fruits[1] = "orange"
console.log(fruits[1]) //orange
  • 선언 : new Array(" 혹은 [] 를 통해 선언하며, 사이즈 혹은 값ㅇ르 입력하여 초기화도 가능
  • 접근 : Array[index]를 통해 index를 통하여 O(1) 접근
  • 배열 : Array.length를 통해 배열 요소의 개수 확인 가능


배열의 실체

let nums = []

nums[0] = "one"
nums[1] = "two"

console.log(nums.length) //2
console.log(nums) //[ 'one', 'two' ]
console.log(Object.getOwnPropertyDescriptors(nums))
// {
//     '0': {
//       value: 'one',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     },
//     '1': {
//       value: 'two',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     },
//     length: { value: 2, writable: true, enumerable: false, configurable: false }
//   }

nums["once"] = "once"
nums["twice"] = "twice"
console.log(nums.length) //2 🤭🤭🤭
console.log(nums) //[ 'one', 'two', once: 'once', twice: 'twice' ]
console.log(Object.getOwnPropertyDescriptors(nums))

// {
//     '0': {
//       value: 'one',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     },
//     '1': {
//       value: 'two',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     },
//     length: { value: 2, writable: true, enumerable: false, configurable: false },
//     once: {
//       value: 'once',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     },
//     twice: {
//       value: 'twice',
//       writable: true,
//       enumerable: true,
//       configurable: true
//     }
//   }

// 0, 1, once, twice key 값으로 이루어짐 > hash
  • js에서 배열은 다른 언어에서 말하는 일반적인 배열이 아닌 Hash 기반의 객체
  • 메모리가 연속적인 밀집 배열(dense array)가 아닌 비 연속적인 희소 배열(sparse array)
  • 결국 배열도 내부적으로는 key-value로 작동한다


배열 타입 확인 및 요소 삭제

let num = 123.456
let str = "hello"
let fruits = ["apple", "banana", "melon"]

console.log(Array.isArray(num)) //false
console.log(Array.isArray(str)) //false
console.log(Array.isArray(fruits)) //true

delete fruits[1]
console.log(fruits) //[ 'apple', <1 empty item>, 'melon' ]
console.log(fruits[1]) //undefined
console.log(fruits.length) //3
// 값은 삭제됐지만 공간은 남아있어 길이가 그대로다
// 사용 지양!!
  • 배열 타입 확인 방법 : Array.isArray(value)
  • 배열 일부 요소 삭제 : delete array[index] (삭제해도 배열 사이즈가 그대로인 문제점)



2. 배열 조작

배열 추가/삭제

let fruits = ["apple", "banana", "melon"]

let ret = fruits.push("watermelon")
console.log(fruits) //[ 'apple', 'banana', 'melon', 'watermelon' ]
console.log(fruits.length) //4
console.log(ret) //4 push 는 배열의 최종 길이를 리턴한다!

let ret2 = fruits.pop()
console.log(fruits) //[ 'apple', 'banana', 'melon' ]
console.log(fruits.length) //3
console.log(ret2) //watermelon pop한 아이 이름을 말하는구나

let ret = fruits.unshift("watermelon")
console.log(fruits) //[ 'watermelon', 'apple', 'banana', 'melon' ]
console.log(fruits.length) //4
console.log(ret) //4 unshift 는 배열의 최종 길이를 리턴한다!

let ret2 = fruits.shift()
console.log(fruits) //[ 'apple', 'banana', 'melon' ]
console.log(fruits.length) //3
console.log(ret2) //watermelon shift한 아이 이름을 말하는구나
  • LIFO - Back > 배열 추가 : Array.push(element), 배열 삭제 : Array.pop()
  • LIFO - Front > 배열 추가 : Array.unshift(element), 배열 삭제 : Array.shift()
  • 추가 시 리턴값 추가된 배열
  • 삭제 시 리턴값 삭제된 value


배열 삭제/변경 (index)

let fruits = ["apple", "banana", "melon"];

let ret = fruits.splice(1); // 1번째부터 다 없애
console.log(ret); //[ 'banana', 'melon' ] splice 는 잘린 애들 반환
console.log(fruits); //[ 'apple' ]

fruits = ["apple", "banana", "melon", "watermelon"];

ret = fruits.splice(2, 2); // 2번째것부타 2개 잘라
console.log(ret); //[ 'melon', 'watermelon' ]
console.log(fruits); //[ 'apple', 'banana' ]

fruits = ["apple", "banana", "melon", "watermelon"];
ret = fruits.splice(2, 2, "manggo", "orange"); // 2번째것부타 2개 잘르고 그 자리에 이걸 넣어
console.log(ret); //[ 'melon', 'watermelon' ]
console.log(fruits); //[ 'apple', 'banana', 'manggo', 'orange' ]
  • 배열 요소 삭제/변경 : Array.splice(index[,deleteNum,elem1,...,elem2])
  • splice 는 기존 배열 자체를 수정한다.


배열 삭제 (index), 배열 병합

let fruits = ["apple", "banana", "melon"];

// slice, concat 모두 불변성 > 새 배열 반환

let ret = fruits.slice(1); // 1번째부터 끝까지 가져와서 새로운 배열 반환 && 원본 데이터에 영향 안미친다.
console.log(ret); //[ 'banana', 'melon' ] slice 는 잘린 애들 반환
console.log(fruits); //[ 'apple', 'banana', 'melon' ] fruits 는 변하지 않아

fruits = ["apple", "banana", "melon"];
ret = fruits.slice(1, 2); // 1번째부터 2번째 전까지
console.log(ret); //[ 'banana' ]
console.log(fruits); //[ 'apple', 'banana', 'melon' ]

fruits = ["apple", "banana", "melon"];
ret = fruits.slice(-2); // 음수도 된다. 
console.log(ret); //[ 'banana', 'melon' ]
console.log(fruits); //[ 'apple', 'banana', 'melon' ]

fruits = ["apple", "banana", "melon"];
let fruits_add = ["cherry", "orange"]

console.log(fruits.concat(fruits_add)) //[ 'apple', 'banana', 'melon', 'cherry', 'orange' ]
console.log(fruits); //[ 'apple', 'banana', 'melon' ]
  • 배열 요소 삭제 : Array.slice([start],[end])
  • start 부터 end-1 까지
  • 다중 배열 병합 : Array.concat(arg1, arg2...)
  • slice, concat은 원본 배열은 수정되지 않는다. > 새로운 배열 반환


배열 반복문

let fruits = ["apple", "banana", "melon"];

for (let i = 0; i<fruits.length; i++){
    console.log(fruits[i])
}

for (let fruit of fruits) {
    console.log(fruit)
}

for (let key in fruits) {
    console.log(key) // 0 1 2
    console.log(fruits[key])
}
  • 다양한 반복문 문법을 통해 배열 요소에 접근 가능
  • for...length, for...of, for...in
  • for-of > 내부 이터레이션으로 해당 인덱스의 value 반환
  • for-in > 키 값에 대한 접근으로 배열에서는 index 반환



3. 배열 탐색

let fruits = ["apple", "banana", "melon", "banana"];
// split, join 원시 데이터 불변

let str = fruits.join() 
console.log(fruits) //[ 'apple', 'banana', 'melon', 'banana' ]
console.log(str) //apple,banana,melon,banana

str = fruits.join(";") 
console.log(fruits) //[ 'apple', 'banana', 'melon', 'banana' ]
console.log(str) //apple;banana;melon;banana

let str_array = str.split(";")
console.log(str_array) //[ 'apple', 'banana', 'melon', 'banana' ]
console.log(str) //apple;banana;melon;banana
  • index 탐색(앞에서부터) : Array.indexOf(item, from)
  • index 탐색(뒤에서부터) : Array.lastIndexOf(item, from)
  • 값 포함 여부 확인 : Array.includes(item, from)
  • join / splice 통해서 arr / string 변환 가능 하다



나의 회고 🤫

slice 와 concat 은 기존 arr 가 불변한다는 사실 잊지 말기!
배열은 코테의 필수 요소이기 때문에 적어도 1주일에 한번씩 개념 내용 보면서 익숙해지도록 하자
delete arr[index] 사용 금지