Javascript - 배열과 배열 처리

kimhanna·2020년 11월 8일
0

배열 요소 조작

배열 메서드 중 일부는 배열 자체를 수정하며, 다른 일부는 새 배열을 반환한다. 예를 들어 push는 배열 자체를 수정하며, concat은 새 배열을 반환한다. 메서드 이름에 이런 차이점에 대한 힌트가 전혀 없으므로 프로그래머가 전부 기억해야 한다.

배열의 처음이나 끝에서 요소 하나를 추가하거나 제거하기
배열의 첫번째 요소는 인덱스가 0인 요소를 말하며, 마지막 요소는 arr.length - 1 인 요소를 말한다.
push pop은 각각 배열의 끝에 요소를 추가하거나 제거하고,shift unshift는 각각 배열의 처음에 요소를 추가하거나 제거한다.

push / unshift 는 새 요소를 추가해서 늘어난 길이를 반환하고,
pop / shift 는 제거된 요소를 반환한다.

const arr = [1, 2, 3];
arr.push(4); // arr = [1, 2, 3, 4]
arr.pop(); // 4 arr = [1, 2, 3]
arr.unshift(0) // arr = [0, 1, 2, 3]
arr.shift() // 0 arr = [1, 2, 3]

배열 일부 가져오기 - slice

배열의 일부만 가져올 때는 slice 메서드를 사용합니다. 매개변수 두 개를 받는데, 첫 번째 매개변수는 어디서부터 가져올지를, 두 번째 매개변수는 어디까지 (바로 앞 인덱스까지 가져옴) 가져올지를 지정한다. 두 번째 매개변수 생략 시 배열의 마지막까지 반환한다.
이 메서드에서는 음수 인덱스를 쓸 수 있고, 음수를 쓰면 배열의 끝에서 부터 요소를 센다.

const arr = [1, 2, 3, 4, 5];
arr.slice(3);		// [4, 5] arr은 바뀌지 않음.
arr.slice(2, 4);	// [3, 4]
arr.slice(-2);		// [4, 5] 

임의의 위치에 요소 추가 또는 제거하기 - splice
splice는 배열을 자유롭게 수정할 수 있다. 첫 번째 매개변수는 수정을 시작할 인덱스이고, 두 번째 매개변수는 제거할 요소 숫자이다. 아무 요소도 제거하지 않을 때는 0을 넘기고 나머지 매개변수는 배열에 추가될 요소이다.

const arr = [1, 5, 7];

arr.splice(1, 0, 2, 3, 4); // arr = [1, 2, 3, 4, 5, 7] 제거없음.
arr.splice(5, 0, 6); // arr = [1, 2, 3, 4, 5, 6, 7] 제거없음.
arr.splice(1, 2); // arr = [1, 4, 5, 6, 7] 제거 [2, 3]
배열 안에서 요소 교체하기 - copyWithin
copyWithin은 ES6에서 도입한 새 메서드로 배열 요소를 복사해서 다른 위치에 붙여넣고, 기존의 요소를 덮어쓴다. 첫 번째 매개변수는 복사한 요소를 붙여넣을 위치이고, 두 번째 매개변수는 복사를 시작할 위치이고, 세 번째 매개변수는 (생략가능) 복사를 끝낼 위치이다. slice와 마찬가지로 음수를 사용하면 배열의 끝에서 부터 센다.

const arr = [1, 2, 3, 4];

arr.copyWithin(1, 2) // arr = [1, 3, 4, 4]
arr.copyWithin(2, 0, 2) // arr = [1, 3, 1, 3]
arr.copyWithin(0, -3, -1) // arr = [3, 1, 1, 3]
특정 값으로 배열 채우기 - fill
fill은 ES6에서 도입한 환영할만한 좋은 메서드로 정해진 값으로 배열을 채운다. 크기를 지정해서 배열을 생성하는 Array 생성자와 잘 어울린다.
배열의 일부만 채우려 할 때는 시작 인덱스와 끝 인덱스를 지정해주면 된다. 음수 인덱스도 사용할 수 있다.

const arr = new Array(5).fill(1) // arr = [1, 1, 1, 1, 1]로 초기화됨

arr.fill("a"); // arr = ["a", "a", "a", "a", "a"]
arr.fill("b", 1) // arr = ["a", "b", "b", "b", "b"]
arr.fill("c", 2, 4) // arr = ["a", "b", "c", "c", "b"]
arr.fill(5.5, -4) // arr = ["a", 5.5, 5.5, 5.5, 5.5]
배열 정렬과 역순 정렬 reverse / sort
reverse는 이름 그대로 배열 요소의 순서를 반대로 바꾼다.

const arr = [1, 2, 3, 4, 5];

arr.reverse(); // arr = [5, 4, 3, 2, 1];
sort는 배열 요소의 순서를 정렬한다.

const arr = [5, 3, 2, 4, 1];
arr.sort(); // arr = [1, 2, 3, 4, 5];
sort는 정렬 함수를 받을 수 있다. 이 기능은 매우 편리하며, 예를 들어 일반적으로는 객체가 들어있는 배열을 정렬할 수 없지만, 정렬 함수를 사용하면 가능하다.

const arr = [
{name: "Dany"},
{name: "Suzan"},
{name: "Aria"},
{name: "Cookey"},
];

arr.sort(); // arr은 바뀌지 않음
arr.sort((a,b) => a.name > b.name); // arr은 name프로퍼티의 알파벳 순으로 정렬됨
arr.sort((a,b) => a.name[1] > b.name[1]); // arr은 name프로퍼티의 두 번째 글자의 알파벳 역순으로 정렬됨
배열 검색
배열 안에서 뭔가 찾으려 할 때는 몇가지 방법이 있다.

indexOf / lastIndexOf
indexOf 는 찾고자 하는 것과 정확히 일치 (===)하는 첫 번째 요소의 인덱스를 반환한다. indexOf의 짝인 lastIndexOf는 배열의 끝에서부터 검색한다. 배열의 일부분만 검색하려면 시작 인덱스를 지정할 수 있다. indexOf 와 lastIndexOf 는 일치하는 것을 찾지 못하면 -1을 반환한다.

const o = {name: "Jerry"};
const arr = [1, 5, "a", o, true, 5, [1, 2], "9"];

arr.indexOf(5); // 1
arr.lastIndexOf(5); // 5
arr.indexOf("a"); // 2
arr.lastIndexOf("a"); // 2
arr.indexOf({name: "Jerry"}); // -1 찾지못함
arr.indexOf(o); // 3
arr.indexOf("a", 5) // -1 찾지못함
findIndex
findIndex 는 일치하는 것을 찾지 못했을 때 -1을 반환한다는 점에서는 indexOf와 비슷하지만, 보조 함수를 써서 검색 조건을 지정할 수 있으므로 indexOf보다 더 다양한 상황에서 활용할 수 있다.
하지만 findIndex는 검색을 시작할 인덱스를 지정할 수 없고, 뒤에서 부터 찾는 findLastIndexOf 같은 짝도 없다.

const arr = [
{id: 5, name: "Judith"},
{id: 7, name: "Francis"}
];

arr.findIndex(o => o.id === 5); // 0
arr.findIndex(o => o.name === "Francis"); // 1
arr.findIndex(o => o.id === 3); // -1
indexOf와 findIndexOf는 조건에 맞는 요소의 인덱스를 찾을 때 알맞지만, 조건에 맞는 요소의 인덱스가 아니라 요소 자체를 원할 때는 find를 사용한다.

find 는 findIndex와 마찬가지로 검색 조건을 함수로 전달할 수 있고, 조건에 맞는 요소가 없을 때는 undefined를 반환한다.

const arr = [
{id: 5, name: "Judith"},
{id: 7, name: "Francis"}
];

arr.find(o => o.id === 5) // {id: 5, name: "Judith"} 객체 반환
arr.find(o => o.id === 2); // undefined
find와 findIndex에 전달하는 함수는 배열의 각 요소를 첫 번째 매개변수로 받고, 현재 요소의 인덱스와 배열 자체도 매개변수로 받는다. 이런 점을 다양하게 응용할 수 있다.

예를 들어 특정 인덱스보다 뒤에 있는 제곱수를 찾아야 하는 경우.

const arr = [1, 17, 16, 5, 4, 16, 10, 3, 49];

arr.find((x, i) => i > 2 && Number.isInteger(Math.sqrt(x))); // 4
find와 findIndex에 전달하는 함수의 this도 수정할 수 있다. 이를 이용해서 함수가 객체의 메서드인 것처럼 호출할 수 있다.

ID를 조건으로 Person 객체를 검색하는 예제. 두 방법의 결과는 같다.

class Person {
constructor(name) {
this.name = name;
this.id = Person.nextId++;
}
}

Person.nextId = 0;
const jamie = new Person("jamie"),
juliet = new Person("juliet"),
peter = new Person("peter"),
jay = new Person("jay");

const arr = [jamie, juliet, peter, jay];

// option 1 = ID를 직접 비교
arr.find(p => p.id === juliet.id); // juliet 객체

// option 2 = this 매개변수 이용
arr.find(function(p){
return p.id === this.id
}, juliet); // juliet 객체
이런 간단한 예제에서는 find와 findIndex에서 this 값을 바꾸는 의미가 별로 없지만, 나중에는 더 유용하게 쓰이는 경우가 있다.

some / every
some은 조건에 맞는 요소를 찾으면 즉시 검색을 멈추고 true를 반환하며, 조건에 맞는 요소를 찾지 못하면 false를 반환한다.

const arr = [5, 7, 12, 15, 17];

arr.some(x => x%2 === 0); // true 12는 짝수
arr.some(x => Number.isInteger(Math.sqrt(x))); // false 제곱수가 없음
every는 배열의 모든 요소가 조건에 맞아야 true를 반환하며, 그렇지 않다면 false를 반환한다.

const arr = [4, 6, 16, 36];

arr.every(x => x%2 === 0); // true 모두 짝수
arr.every(x => NumberisInteger(Math.sqrt(x))); // false 6은 제곱수가 아님
map과 filter
map과 filter는 배열 메서드 중 가장 유용한 메서드이다.

map은 배열 요소를 변형한다. 일정한 형식의 배열을 다른 형식으로 바꿔야 할 때 사용하면 된다. map과 filter 모두 사본을 반환하며 원래 배열은 바뀌지 않는다.

const cart = [
{name: "Widget", price: 9.95},
{name: "Gadget", price: 22.95}
];
const names = cart.map(x => x.name); // ["Widget", "Gadget"]
const prices = cart.map(x => x.price); // [9.25, 22.95]
const discountPrices = price.map(x => x * 0.8); // [7.96, 18.36]
filter는 이름이 암시하듯 배열에서 필요한 것을만 남길 목적으로 만들어졌다. 주어진 함수의 테스트를 통과한 요소를 모아 새로운 배열을 반환한다.

const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];

words.filter(word => word.length > 6); // ["exuberant", "destruction", "present"]
reducer
map이 배열의 각 요소를 변형한다면 reduce는 배열 자체를 변형한다. reduce라는 이름은 이 메서드가 보통 배열을 값 하나로 줄이는 데 쓰이기 때문에 붙었습니다.

reduce는 map과 filter를 비롯해 여태까지 배운 배열 매서드의 동작을 대부분 대신할 수 있다. 콜백 함수를 받고 여태까지 첫 번째 매개변수는 항상 현재 배열 요소였지만, reduce가 받는 첫 번째 매개변수는 배열이 줄어드는 대상인 어큐물레이터(accumulator)이다. 두 번째 매개변수부터는 콜백의 순서대로 현재 배열 요소, 현재 인덱스, 배열 자체이다.

문자열 병합
배열의 문자열 요소들을 몇몇 구분자로 합치려 할 때가 많은데, Array.prototype.join은 매개변수로 구분자 하나를 받고 요소들을 하나로 합친 문자열을 반환한다. 매개변수 생략시 기본값은 쉼표이며, 문자열 요소를 합칠 때 정의되지 않은 요소, 삭제된 요소, null, undefined는 모두 빈 문자열로 취급함.

delete arr[3];
arr.join();		// "1,,hello,,true,"
arr.join('');	// "1hellotrue"
arr.join(' -- ');	// "1 -- -- hello -- -- true -- "
profile
한 줄의 코드가 유저의 일상을 변화시키는 매력에 반해 프론트엔드 개발자가 되었습니다. 늘 배움의 자세로 유저를 위한 기술을 구현하겠습니다. 저는 함께 이뤄내는 결과의 가치를 믿습니다.

0개의 댓글