for...in, for...of
/**
* for문은 도중에 아이템을 제거해버리면 제대로 돌지 않는다.
*/
const arr = [1, 2, 3, 4, 5];
for(let item of arr){
arr.shift();
console.log(arr);
console.log(item); // 1 3 5
}
/**
* for of도 내부적으로는 for(let i = 0 ; i < arr.length ; i++) 이런식으로 동작하기 때문에,
* 당연하게도 도중에 배열 아이템이 사라져버리면 배열 길이만큼 반복하지 않는다.
* 이렇게 놓고 보면 당연한데도, 왜 내가 생각한 횟수만큼 돌지 않는지 고민했다. 멍청하게 헤매지 말자.
*
* 원본 배열을 복제한 배열로 작업을 하던가,
* splice, pop, shift처럼 아이템을 삭제하는 대신
* 값이 없음을 표현하는 값을 대입해서 사용하자.
*/
/**
* for of와 for in의 차이
*/
const arr2 = ['a', 'b', 'c'];
for(const item in arr2){
console.log('in', item); // 0 1 2
}
for(const item of arr2){
console.log('of', item); // a b c
}
/**
* for in에서의 item은 배열의 index다.
* for of에서의 item은 배열의 객체다.
*/
// for..of와 for..in의 차이점과 유의할 점
// for..of는 Array, Map, Set, String 등 반복가능한 객체에 대해 사용가능하다.
var arr = ['a', 'b', 'c'];
for (let i of arr) {
console.log(i); // 'a', 'b', 'c'
}
// for..in은 객체의 반복을 위해 만들어진 메서드이며,
// 객체의 속성을 반환한다.
// *** 배열의 인덱스 반환용으로 만들어진 메서드가 아님에 주의!!
// 배열에 사용해도 i는 string 타입으로 반환된다.
// 또한 순서를 보장하지 않기 때문에 배열에서는 for, forEach, for..of를 사용하는 것이 좋다.
for (let i in arr) {
console.log(i, typeof i); // '0', 'string'
}
forEach
반환값 undefined (메서드 체인 중간에 사용불가)
원본변경 X (callback에서는 가능)
반복중 배열 변경시 반복 생략됨
콜백함수 인자 (currentValue[, index[, array]]) 요소 값, 요소 인덱스, 순회 중인 배열
const array1 = ['a', 'b', 'c'];
array1.forEach(element => console.log(element));
// expected output: "a"
// expected output: "b"
// expected output: "c"
every, some
공통점
반환값 boolean
원본변경 X (callback에서는 가능)
콜백함수 인자 (currentValue[, index[, array]]) 요소 값, 요소 인덱스, 순회 중인 배열
차이점
every | some |
배열 안의 모든 요소가 주어진 판별 함수를 통과하는지 테스트 반복중 거짓인 경우 즉시 false 반환(나머지 인덱스는 반복하지 않음) 빈 배열에서 호출시 무조건 true 반환 |
배열 안의 어떤 요소라도 주어진 판별 함수를 통과하는지 테스트 반복중 참인 경우 즉시 true 반환(나머지 인덱스는 반복하지 않음) 빈 배열에서 호출시 무조건 false 반환 |
var arr = [1, 2, 3];
arr.every(item => item > 2); // false
arr.every(item => item > 0); // true
arr.some(item => item > 2); // true
arr.some(item => item > 3); // false
findIndex, indexOf, lastIndexOf
// 인덱스를 찾아 반환하는 함수들
const arr = [2, 5, 9, 2];
// findIndex
// 주어진 판별함수를 만족하는 첫번째 요소의 인덱스를 반환
// 없으면 -1
arr.findIndex((item) => item > 3); // 1
arr.findIndex((item) => item > 10); // -1
// indexOf
// 정해진 요소의 첫번째 인덱스를 반환
// 없으면 -1
arr.indexOf(2) // 0
arr.indexOf(10) // -1
// 두 번째 인자로 start index를 지정할 수 있다.
arr.indexOf(2, 1) // 3
// lastIndexOf
// 정해진 요소를 배열 맨 뒤에서부터 찾아 인덱스를 반환
// 없으면 -1
arr.lastIndexOf(2) // 3
arr.indexOf(10) // -1
// 두 번째 인자로 start index를 지정할 수 있다.
arr.indexOf(2, 2) // 0
flat(배열 평탄화)
매개변수는 얼마나 깊은 배열까지 평탄화할 것인지. default 1
const arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
배열 요소 중복제거
(Symbol을 제외한)원시 자료형은 아래 방법으로 중복을 제거할 수 있다.
String, Number, BigInt, Boolean, undefined, null
// Set 사용
Array.from(new Set(arr));
// [...new Set(arr)] 과 동일
// filter
arr.filter((item, index) => arr.indexOf(item) === index);
// reduce
arr.reduce(
(unique, item) => (unique.includes(item) ? unique : [...unique, item]),
[]
);
참조 자료형은 위 방법으로 중복이 제거되지 않는다.
함수, 배열, 객체
배열이나 객체의 중복 제거를 원할시엔 JSON.parse(JSON.stringify(arr))를 사용하는 편법?이 존재한다.
var arr = [{a:1}, {a:1}];
var stringified = arr.map(a => JSON.stringify(a)); // ["{\"a\":1}", "{\"a\":1}"]
var unique = [...new Set(stringified)]; // ["{\"a\":1}"]
var result = unique.map(u => JSON.parse(u)); // [{a:1}]
// 축약
[...new Set(arr.map(a=>JSON.stringify(a)))].map(u=>JSON.parse(u));
splice
특정인덱스의 중간요소제거
/**
* splice
* 배열 기존 요소 삭제, 교체, 추가 (원본 변경)
*/
// arr.splice(인덱스, 교체할 갯수, [교체할 요소])
// 첫번째 인자 : 몇번째 인덱스에 넣을것인지
// 두번째 인자 : 0이면 교체하지 않고 추가만 함. 배열 길이보다 길면 인덱스 이후로 모두 제거
// 세번째 인자 : 교체할 요소가 없으면 삭제만 함
// 리턴값 : 제거된 요소들의 배열
arr.splice(1, 0, 100); // arr[1] 순서에, 아무것도 삭제하지 않고, 100을 추가
// arr = [1, 100, 2, 3];
// 리턴값 []
arr.splice(1, 2, 100); // arr[1]부터, 2개를 제거하고, 100을 추가
// arr = [1, 100];
// 리턴값 [2, 3];
arr.splice(1, 10); // arr[1]부터, 10개를 제거
// arr = [1];
// 리턴값 [2, 3];
/**
* slice
* 얕은 복사 후 새로운 배열로 반환함(원본 보존)
*/
arr = ["a", "b", "c", "d", "e"];
arr.slice(2);
// arr[2]부터 잘라서 반환함.
// ['c', 'd', 'e']
arr.slice(1, 3);
// arr[1] 이상 arr[3] 미만
// [b', 'c']
shift unshift pop push
배열 요소 추가 삭제
arr = [1, 2, 3];
/**
* 원본 배열이 변경되는 방식
*/
// 배열 맨 뒤에 값 추가 & 배열 길이 반환
const pushed = arr.push(0);
// pushed = 4
// arr = [1, 2, 3, 0]
// 배열 맨 앞에 값 추가 & 배열 길이 반환
const unshifted = arr.unshift(0);
// unshifted = 4
// arr = [0, 1, 2, 3]
// 배열 맨 끝 값 제거 & 제거된 요소 반환
const popped = arr.pop();
// popped = 3
// arr = [1, 2]
// 배열 맨 앞 값 제거 & 제거된 요소 반환
const shifted = arr.shift();
// shifted = 1
// arr = [2, 3]
map, filter, reduce
별도로 정리해 둠 : map vs filter vs reduce 보러가기
'Web development > Algorithm' 카테고리의 다른 글
[프로그래머스] 카펫 (완전탐색/javascript) (0) | 2021.08.26 |
---|---|
일곱 난쟁이 (완전탐색/javascript) (0) | 2021.08.25 |
[Javascript Cheet Sheet] 숫자 다루기 (0) | 2021.08.25 |
[프로그래머스] 단속카메라 (javascript) (0) | 2021.08.24 |
[프로그래머스] 구명 보트 (javascript) (0) | 2021.08.23 |
댓글