배열과 컬렉션

wh·2022년 4월 4일
0

배열 생성

undefined 로 초기화된 1만개의 요소를 갖는 배열

const bigEmptyArray = []
bigEmptyArray.length = 10000

유사배열객체에서 배열요소를 수집한다. 유사배열 array-like 객체란 length 라는 프로퍼티가 정수값을 갖거나 '0', '1', '2'.. 등으로 계속되는 이름을 가진 프로퍼티를 같는 객체이다.

const arrayLike = { length: 3 , '0': 'Peter', '1': 'Paul', '2': 'Mary'}
const elements = Array.from(arrayLike)
elements // ['Peter', 'Paul', 'Mary']
Array.isArray(arrayLike) // false
Array.isArray(elements) // true

Array.from 메서드의 두번째 인수를 0에서 length-1 까지의 인덱스 값을 반환하는 함수로 받으면 요소와 인덱스가 전달된다.

const square = Array.from({length: 5}, (element, index) => index * index )
square // [0, 1, 4, 9, 16]

length 와 인덱스 프로퍼티

배열의 length 는 0 ~ 2^32 - 1 사이의 숫자. 배열은 length 프로퍼티와 인덱스 프로퍼티 '1', '2', '3', .. 을 갖는 객체다. 프로퍼티키는 항상 문자열이다.

요소삭제 및 추가

배열의 끝에 요소를 추가하거나 마지막 요소를 삭제하는 메서드는 배열의 길이도 바꾼다.

let arr = [0, 1, 4, 9, 16, 25]
const deletedElement = arr.pop()
const newLength = arr.push('x')
arr // [0, 1, 4, 9, 16, 'x']
deletedElement // 25
newLength // 6

배열의 앞에 요소를 추가하거나 처음 요소를 삭제하는 메서드는 배열의 길이도 바꾼다.

arr = [0, 1, 4, 9, 16, 25]
const deletedElement = arr.shift() 
const newLength = arr.unshift('x') 
arr // ['x', 1, 4, 9, 16, 25]
deletedElement // 0
newLength // 6

arr.push(15,25) 
arr // ['x', 1, 4, 9, 16, 25, 15, 25]
arr.unshift(0,1,4) 
arr // [0, 1, 4, 'x', 1, 4, 9, 16, 25, 15, 25]

splice 는 arr.splice(start, deleteCount, x1, x2, ... )

arr = [0, 1, 12, 24, 36]
const start = 2
arr.splice(start, 2, 16, 25) // [12, 24]
arr // [0, 1, 16, 25, 36]
arr.splice(start, 0, 4, 9) // []
arr // [0, 1, 4, 9, 16, 25, 36]
arr.splice(start, 2) // [4, 9]
arr // (5) [0, 1, 16, 25, 36]
arr.splice(start) // [16, 25, 36]
arr // [0, 1]

배열변경자 mutator

arr.fill(value, start, end) - 기존요소를 새로운 요소로 덮어쓴다.
arr.copyWithin(targetIndex, start, end) - 같은 배열의 다른요소로 기존요소를 덮어쓴다.

let arr = [0, 1, 4, 9, 16, 25]
arr.copyWithin(0, 1) // [1, 4, 9, 16, 25, 25]
arr.copyWithin(1) // [1, 1, 4, 9, 16, 25]
arr.fill(7, 3, -1) // [1, 1, 4, 7, 7, 25]
arr.reverse() // [25, 7, 7, 4, 1, 1]

arr.sort(comparisonFunction)
comparisonFunction(x,y) - 음수는 x 가 y 앞, 양수는 x 가 y 뒤, 구별불가

arr = [0, 1, 13, 33, 4, 8]
arr.sort((x,y) => x-y) // [0, 1, 4, 8, 13, 33]
arr.sort() //  [0, 1, 13, 33, 4, 8]

비교함수를 제공하지 않으면 sort 함수는 요소를 문자열로 변환하고 비교한다.


요소생성

지금부터 설명하는 메서드는 기존 배열의 내용을 바꾸지 않고, 기존 배열에 어떤 연산을 적용한 결과를 새로운 배열로 만든다.

arr1 = [0, 1, 13, 33, 4, 8]
arr1.slice(1, 2) // [1]
arr1 // [0, 1, 13, 33, 4, 8]

arr2 = [[1, 2], [3, 4]]
arr2.flat() // [1, 2, 3, 4]

arr1.concat(9,8, arr2) // [0, 1, 13, 33, 4, 8, 9, 8, Array(2), Array(2)]
// = [...arr1, 9, 8, ...arr2]

요소검색

배열에 특정한 값이 있는지 확인

arr.include(target, start) // 참, 거짓
arr.indexOf(target, start) // 첫인덱스 , -1
arr.lastIndexOf(target, start) // 마지막인덱스, -1
arr.findIndex(conditionFunction) // 조건에 맞는 첫번째 인덱스
arr.find(conditionFunction) // 조건에 맞는 첫번째 요소

arr3 = [0, 1, 13, 33, 4, 8, 9, 8]
arr3.find(x => x > 20) // 33
arr3.some(x => x > 20) // true
arr3.every(x => x > 20) // false

다음 메서드의 조건함수에 배열요소, 인덱스, 전체배열을 조건함수의 인수로 받는다.
arr.find
arr.every
arr.some
arr.filter

모든 요소 방문

for of 루프는 0 과 length-1 사이의 모든 인덱스값을 방문하여 빠진요소는 undefined 를 반환한다. 반면 for in 루프는 존재하는 키값만 방문한다.

for (const e of arr) {
  // 요소 e로 작업수행
}

for (const i in arr) {
  // 인덱스 i 와 요소 arr[i] 로 작업수행
}

for ( const [index, element] of arr.entries()) {
  // 인덱스 i 와 요소 element 로 작업수행
}

arr.forEach((element, index) => console.log(element, index))
for (const index in arr) console.log(arr[index], index)

arr.forEach(f) 메서드는 각 요소에 f(element, index, arr) 를 호출한다. 빠진요소는 생략한다.
arr.map(f) 는 f(element, index, arr) 의 결과값을 포함하는 배열을 반환한다.

[1,7,2,9].map(x => x * x) // [1, 49, 4, 81]
[1,7,2,9].join(' and ') // '1 and 7 and 2 and 9'

forEach, map, filter, find, findIndex, some, every 메서드의 함수 f 는 함수인수뒤에 선택형인수 thisArg 를 받는다. thisArg 는 함수 f 의 this 매개변수가 된다. 각 인덱스로 thisArg.f(element, index, arr) 함수를 호출한다.

희소배열 sparse array

한개이상의 요소가 빠진 배열을 희소배열이라 하며, 다음과 같은 경우 생긴다.

  • 배열리터럴에 요소가 빠짐
  • length 너머로 배열을 추가
  • length 를 증가
  • 요소를 삭제
somNumber = [,2,,9]
somNumber[100] = 1
somNumber.length[200]
delete someNumber[1]

배열 api 의 대부분은 희소배열에서 빠진 요소를 생략한다. 예를 들어, forEach 는 빠진요소를 생략한다. 반면 Array.from(arrayLike, f) 는 예외이며 모든 요소에 f 를 호출하며 빠진요소는 undefined 가 반환된다.
배열을 제공했을때 새로운 배열을 반환하는 대부분의 메서드는 빠진요소를 그대로 유지한다.
sort 메소드는 빠진 요소를 뒤로 배치한다. filter 함수를 이용해 빠진 요소를 제거할수 있다

Array.from([,,9,10,,1])  // [undefined, undefined, 9, 10, undefined, 1]
[,2,,9].map(x => x*x) // [, 4, , 81]
[,2,,9].sort() // [2, 9, , ,]
[,2,,9].filter( x => true ) // [2, 9]

리듀스

map 메서드는 컬렉션의 모든 요소가 인수가 한개인 단한함수 unary function 을 적용한다. 이번절에서 설명하는 reduce, reduceRight 메서드는 이항연산다 binary operator 를 이용해 두개의 요소를 합친다.

const arr = [1,7,2,9]
const result = arr.reduce((x,y) => x + y)
result // 19
arr.reduce((x,y) => 10 * x + y) // 1729
arr.reduce((accum,current) => accum - current, 0) // -19

리듀스의 콜백함수는 실제로 다음 네개의 인수를 받는다.
( 누적된 값, 현재배열요소, 현재배열요소의인덱스, 전체배열 )

function findAll(arr, condition) {
  return arr.reduce(
    (accum, current, currentIndex) => 
    	condition(current) ? [...accum, currentIndex] : accum,
    []
  )
}
const odds = findAll([1,7,2,9], x => x % 2 !== 0) // [0, 1, 3]

문자열 빈도 맵


// loop 
const freq = {}
for (const c of 'Mississippi') {
  if (c in freq) {
    freq[c] ++
  } else {
    freq[c] = 1
  }
} // {M: 1, i: 4, s: 4, p: 2}


// reduce
[...'Mississippi'].reduce(
  (freq, c) => ({...freq, [c]: (c in freq ? freq[c] + 1: 1) }),
  {}) // {M: 1, i: 4, s: 4, p: 2}

모든 자바스크립트 객체가 맵이지만 Map클래스를 직접사용하면 다음과 같은 장점이 있다.

  • 객체키는 반드시 문자열이나 심벌이어야하지만 Map키는 형식에 제한이 없다.
  • Map 인스턴스는 요소를 추가한 순서를 기억한다.
  • 객체와 달리 Map은 프로토타입 체인을 갖지 않는다.
  • size 프로퍼티로 항목의 수를 확인할 수 있다.
const weekdays = new Map(
 [["Mon", 0], ["Tue", 1], ["Wed", 2], ["Thu", 3], ["Fri", 4], ["Sat", 5], ["Sun", 6], ])
// Map(7) {'Mon' => 0, 'Tue' => 1, 'Wed' => 2, 'Thu' => 3, 'Fri' => 4, …}

const emptyMap = new Map()
// 항목추가 연쇄적으로 호출가능
map.set(key1, value1).set(key2, value2)
// 항목삭제 , clear 모두 삭제
map.delete(key) //  // Returns true if the key was present, false otherwise
// 키존재여부
if (map.has(key)) . . .
// 키의 값
const value = map.get(key)   // Returns undefined if the key is not present

// 모든항목 루프
for (const [key, value] of map) {
 console.log(key, value)
}

map.forEach((key, value) => {
 console.log(key, value)
})

세트

세트는 중복을 허용하지 않는 요소들의 집합자료구조

const weekdays = new Set(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
//  {'Mon', 'Tue', 'Wed', 'Thu', 'Fri', …}
const emptySet = new Set()
const setWithElements = new Set(iterable
set.add(x)
 // Adds x if not present and returns set for chaining
set.delete(x)
 // If x is present, deletes x and returns true, otherwise returns false
set.has(x) // Returns true if x is present
set.clear() // Deletes all elements

for (const value of set) {
 console.log(value)
}

set.forEach(value => {
 console.log(value)
})

위크맵과 위크셋 WeakMap WeakSet

위크맵

  • 키가 반드시 객체
  • 키로 사용된 객체를 참조하는 것이 아무것도 없다면 해당 객체는 메모리와 위크맵에서 자동으로 삭제
  • weakMap.get(key), weakMap.set(key, value), weakMap.delete(key), weakMap.has(key)

위크셋

  • 객체만 저장할 수 있다
  • 객체는 도달 가능할 때만 메모리에서 유지
  • add, has, delete

형식화배열 Typed Arrays

같은 형식으로 구성된 일련의 숫자를 효율적으로 저장하려면 형식화 배열을 이용한다.
Int8Array
Uint8Array
Uint8ClampedArray
Int16Array
Uint16Array
Int32Array
Uint32Array
Float32Array
Float64Array

ArrayBuffer

파일, 데이타스트림, 이미지등을 포함하는 연속적인 바이트시퀀스를 가리킨다. 형식화 배열의 데이타도 ArrayBuffer 에 저장한다.
다양한 웹API(File api, XMLHttpRequest, WebSocket)가 ArrayBuffer 를 반환한다.

연습문제

profile
js

0개의 댓글

관련 채용 정보