JS - Array에서 사용할 수 있는 다양한 자바스크립트 메소드

김지현·2021년 6월 6일
3

Javascript

목록 보기
3/3
post-thumbnail

Array APIs

들어가기에 앞서, 혹시 틀린 부분이나 수정해야 할 부분이 있다면 가감 없이 지적 부탁드립니다. 🙃

✔️ 자바스크립트에서 배열은 다양한 범위에서 사용된다. 따라서 배열에 적용할 수 있는 API에도 여러 가지가 있다. 따라서 배열을 다양하게 조작할 수 있는 API들에 대해 알아보고자 한다.

우선 배열의 개념에 대해서 다시 한 번 정리해보도록 하자.

배열 (Array)이란?

📚 배열은 서로 연관된 데이터를 하나로 묶는 데이터 상자이다.

배열을 사용하지 않고 일반적인 변수 선언을 통해서도 각각의 데이터를 저장할 수는 있으나, 그렇게 되면 일일이 계속 변수 선언을 해주어야 하므로 코드의 중복은 물론 개발자의 귀찮음까지 덤으로 발생한다. 실질적인 예를 들어 살펴 보자.

// 일반 변수 선언
const name1 = '은서';
const name2 = '민지';
const name3 = '윤지';
const name4 = '하은';
// 배열 변수 선언
const nameList = ['은서', '민지', '윤지', '하은'];

🤔 위 두 코드를 비교했을 때, 어떤 코드가 더 편리할까?

한 눈에 보아도 후자의 경우가 훨씬 편리하고 가독성도 좋다. 서로 연관된 데이터는 배열과 같은 값을 담는 상자를 통해 순차적으로 저장하는 것이 좋다.


배열은 어떻게 구성되어 있을까?

✔️ 배열 내에 들어 있는 값을 요소 (element) 라고 한다.

배열 내에는 어떤 값이든 추가할 수 있으며 String은 String끼리, Number는 Number끼리 담는 것이 아니라 서로 다른 타입의 값들도 함께 저장할 수 있다.

const data = ['hello', 30, true, null, '25'];

배열을 선언하는 방법

📌 배열은 두 가지 방법으로 선언할 수 있다.

첫 번째는 위에서 언급한 것과 같이 배열 변수 선언을 통한 '배열 리터럴'을 통한 방법이고, 두 번째로는 자바스크립트의 내장 객체 중 하나인 '배열 객체'를 사용하는 방법이다. 바로 예시를 들어보자.

// 배열 변수 선언
// 1. 배열 변수 선언과 동시에 값 할당
const arr = [1, 2, 3, 4, 5];

// 2. 빈 배열 선언 후 배열 값을 할당
const myArr = [];
myArr[0] = 1;
myArr[1] = 2;
myArr[2] = 3;
myArr[3] = 4;
myArr[4] = 5;

// 배열 객체 사용
// 1. 배열 개수 미지정
const arr2 = new Array();
arr2[0] = 1;
arr2[1] = 2;
arr2[2] = 3;
arr2[3] = 4;
arr2[4] = 5;

// 2. 배열 개수 지정
const arr3 = new Array(5);
arr3[0] = 1;
arr3[1] = 2;
arr3[2] = 3;
arr3[3] = 4;
arr3[4] = 5;

// 3. 배열 선언과 동시에 값을 할당
const arr4 = new Array(1, 2, 3, 4, 5);

일반적으로 배열 변수 선언 방식을 많이 사용하지만, 배열 객체를 통해서도 경우에 따라 적절하게 배열을 선언할 수 있다. 배열은 위와 같이 미리 배열의 개수를 지정해줄 수도, 혹은 지정하지 않을 수도, 배열 선언과 동시에 값을 할당 해줄 수도 있다.

위 두 가지 방법 모두 가능하긴 하나, 배열 변수 선언 방식을 사용하는 것이 더 좋다고 할 수 있겠다.


배열의 특성

🚀 배열은 index 값을 가진다.

여기서 주의해야 할 점은, 배열의 index 값은 1이 아니라 0부터 시작한다는 점이다.
따라서, 배열 내 첫 번째 요소에 접근하기 위해서는 1이 아니라 0의 값을 주어야 한다.

const animals = ['dog', 'cat', 'rabbit', 'horse'];

console.log(animals[0]); // 'dog'
console.log(animals[1]); // 'cat'

🚀 배열은 그 자체로 객체, 함수를 담을 수 있으며 배열 내에 배열을 담을 수도 있다.

const theArray = [
  {
    'age':25,
    'name':'민주',
    'favorite':'music',
  },
  {
    'age':27,
    'name':'하은',
    'favorite':'movie',
  },
  {
    'age':18,
    'name':'윤지',
    'favorite':'book',
  }
];

console.log(theArray[1].favorite); // 'movie' 
console.log(theArray[2].name); // '윤지'

배열의 다양한 APIs

🚀 배열에 접근하는 방법

배열에 접근하는 방법은 여러 가지가 있다.

먼저 가장 대표적인 방법으로는 'for'문을 통한 배열 접근이다.
그 외에도 for of, forEach 등을 통해 배열에 접근하여 배열의 값을 출력 할 수 있다.

1. for 반복문을 통한 배열의 출력

// for 반복문을 통한 배열의 출력
const animals = ['dog', 'cat', 'rabbit', 'horse'];

for (let i =0; i < animals.length; i++) {
  console.log(animals[i]); // 'dog','cat','rabbit','horse'
}

2. for ~of를 통한 배열의 출력

✔️ for of 문을 통해서 우리는 배열의 value에 접근 가능하다.

const animals = ['dog', 'cat', 'rabbit', 'horse'];

for (let key of animals) {
  console.log(key); // 'dog','cat','rabbit','horse'
} 

3. forEach를 통한 배열의 출력

✔️ forEach는 배열 내 들어 있는 값마다 우리가 전달한 콜백 함수를 수행한다.

🤔 여기서 잠깐, 콜백 함수란?
콜백 함수는 다른 함수의 parameter로 넘겨준 함수를 말한다.
parameter로 받은 함수는 일단은 넘겨 받고, 때가 되면 '나중에 호출(called back)한다' 라는 것이 콜백 함수의 개념이다.

forEach문에서 콜백 함수가 가지는 인자로는 value, index, array가 있다. 즉 해당 배열의 값, index, 배열 전체가 전달 될 수 있다는 의미이다. 바로 예시로 알아보자.

const animals = ['dog', 'cat', 'rabbit', 'horse'];

animals.forEach(function(value, index, array){
  console.log(value, index, array);
 });
  //'dog' 0 [ 'dog', 'cat', 'rabbit', 'horse'], 
 //'cat' 1 [ 'dog', 'cat', 'rabbit', 'horse'],
//'rabbit' 2 [ 'dog', 'cat', 'rabbit', 'horse'],
//'horse' 3 [ 'dog', 'cat', 'rabbit', 'horse']

위와 같이 배열의 값, index 값, 그리고 배열 자체가 출력되는 것을 알 수 있다.
보통 배열 자체는 인자로 잘 주지 않고, 배열의 값과 index 값 정도만 사용하는 경우가 많다.


📚 배열을 조작하는 다양한 방법들

✔️ 배열 내의 값을 추가하고, 빼는 다양한 방법들에 대해서 알아보자.

✚ 값을 더하는 APIs

1️⃣ push: 배열의 맨 끝에 값을 더한다.
2️⃣ unshift: 배열의 맨 앞에 값을 더한다.

− 값을 빼는 APIs

1️⃣ pop: 배열의 맨 끝의 값을 뺀다.
2️⃣ shift: 배열의 맨 앞의 값을 뺀다.

const city = ['울산', '부산', '대구', '대전'];

city.push('서울');
console.log(city); // '울산','부산','대구','대전','서울'

city.pop();
console.log(city); // '울산','부산','대구','대전'

city.unshift('제주');
console.log(city); // '제주','울산','부산','대구','대전'

city.shift();
console.log(city); // '울산','부산','대구','대전'

🚀 지정된 위치에서 배열의 값을 지우는 방법

splice

const fruits = ['apple', 'peach', 'banana', 'watermelon', 'pear', 'kiwi'];

fruits.splice(0, 2);
console.log(fruits); // ['banana','watermelon','pear','kiwi']

위 코드에서 splice(0, 2)에 집중해보자.

splice에서 앞의 값은 배열의 삭제를 시작할 index, 뒤의 값은 시작 index로부터 삭제할 요소의 수를 의미한다.

따라서, index 값이 0에 해당하는 'apple', 그리고 index를 포함한 2개의 요소가 삭제되어야 하므로 'apple', 'peach'가 사라진 나머지 값들이 출력되는 것을 알 수 있다.

slice

const fruits = ['apple', 'peach', 'banana', 'watermelon', 'pear', 'kiwi'];

const someFruits = fruits.slice(0,2);
console.log(someFruits); // ['apple','peach']

slice는 시작 지점부터 끝 지점까지의 추출 값을 새로운 배열 객체로 반환한다. 즉, 원본 배열은 수정되지 않는다.

위 코드에서 보면, index 값이 0인 'apple'과, index 값이 2인 'banana' 사이의 두 값인 'apple', 'peach'가 출력 되었다. 즉, 결과적으로 splice 메소드를 사용하면 (시작 인덱스 값, 끝 인덱스 값-1)의 값들이 출력 되는 것이다.


🚀 두 배열을 합치는 방법

concat

const number = [1, 2, 3];
const number2 = [4, 5, 6];

const numArray = number.concat(number2);
console.log(numArray); // [1,2,3,4,5,6]

✔️ concat 메소드를 사용하면 두 가지 배열을 합칠 수 있다.

위 예시를 참고하면, 두 가지 배열이 있고 number라는 배열에 number2를 합쳤다. 즉, 배열에 concat 메소드를 사용하여 합쳐 넣고자 하는 배열을 인자로 주면 두 배열이 합쳐지는 것이다.


🚀 배열 내의 값을 검사하는 방법

indexOf, includes

const number = [1, 2, 3];
const number2 = [4, 5, 6];

console.log(number.indexOf(1)); // 0
console.log(number.indexOf(3)); // 2
console.log(number.indexOf(6)); // -1

console.log(number2.includes(5)); // true
console.log(number2.includes(7)); // false

✔️ indexOf를 사용하면, 해당 배열에 내가 찾고자 하는 값이 몇 번째 index 값인지 추출할 수 있다. 만약 해당 배열에 없는 값에 대해 index 값을 찾고자 한다면, -1이라는 값이 출력된다.

✔️ includes를 사용하면, 내가 찾고자 하는 값이 해당 배열에 '존재 하는 지 아닌 지'를 알 수 있다. 만약 존재한다면 true, 존재하지 않는다면 false를 통해서 검사 해볼 수 있다. 참고로, includes는 배열뿐만 아니라 문자열에서도 사용 가능하다!


lastIndexOf

const numbers = [1, 2, 3, 4, 5, 6, 3, 6, 4, 5];

numbers.indexOf(3); // 2
numbers.indexOf(4); // 3
numbers.indexOf(5); // 4
numbers.lastIndexOf(3); // 6
numbers.lastIndexOf(4); // 8
numbers.lastIndexOf(5); // 9

indexOf가 있다면, lastIndexOf도 있다!

✔️ 대충 단어 자체에서도 추측을 할 수 있는데, 만약 한 배열 내에 동일한 값이 있다면 lastIndexOf는 뒤에 있는 값의 index 값을 출력한다. 두 메소드의 기능이 다르니, indexOf와 lastIndexOf를 적절히 활용해서 사용하면 좋겠다.


🚀 배열을 문자열로, 문자열을 배열로 만드는 방법

const introduce = ['은지는', '회사에', '간다'];

const arrayString = introduce.join(' ');
console.log(arrayString); // '은지는 회사에 간다'

const string = '은지는,회사에,간다';
const stringArray = string.split(',');
console.log(stringArray); // ['은지는', '회사에', '간다']
const introduce = ['은지는', '회사에', '간다'];

const reverseArray = introduce.reverse();
console.log(reverseArray);// ['간다','회사에','은지는']

1️⃣ join: 배열을 문자열로 만들어 준다. join은 굳이 구분자를 전달해주지 않아도 된다. 하지만 (''), (' '), (',') 등의 구분자들을 통해 다양한 형식의 문자열로 만들 수 있다.

2️⃣ split: 문자열을 배열로 만들어 준다. split을 사용할 때는 구분자가 꼭 필요하다. 구분자를 넣어 주지 않으면 문자열 그대로 출력되므로, 꼭 구분자를 넣어 주도록 하자.

3️⃣ reverse: 배열의 순서를 거꾸로 만들어 준다.


🚀 원하는 조건을 만족하는 배열을 찾는 방법

find


class Prices {
  constructor(name, price){
    this.name = name;
    this.price = price;
  }
}

const price = [
  new Prices ('grape',5200),
  new Prices ('melon',6000),
  new Prices ('watermelon',6200),
];

const result = price.find(function (priceValue){
  return priceValue.price > 5000;
});

console.log(result);

결과


filter

class Prices {
  constructor(name, price){
    this.name = name;
    this.price = price;
  }
}

const price = [
  new Prices ('apple',3000),
  new Prices ('melon',4500),
  new Prices ('grape',5200),
];

const result2 = price.filter(function (prices) {
  return prices.price >= 3000; 
});

console.log(result2);

결과

✔️ find, filter 모두 콜백 함수를 인자로 받는다.

🤔 얼핏 보면, 이 두 메소드의 차이가 와 닿지 않는다. 하지만 분명한 차이가 있으니 혼동하지 말도록 하자!

1️⃣ find는 조건을 만족하는 결과를 출력하되, true인 값을 하나만 만나도 함수가 종료된다. 즉, 그 조건을 만족하는 값이 뒤에 더 있다고 하더라도 최초로 true를 만나게 되면 함수가 종료된다.

따라서, 위 결과를 보면 모든 과일 요소들의 가격이 5000원 이상이지만, 최초로 그 조건을 만족한 (true) 'grape'만 출력되는 것을 알 수 있다.

2️⃣ filter는 각각의 배열의 원소에 대해서 전달 받은 함수의 조건을 만족하는, 즉 true인 결과들을 모아서 하나의 배열로 만들어 출력 한다.

위 결과를 보면, 3000원 이상이라는 조건을 모든 요소가 만족하므로, length가 3인 배열을 만들어 낸 것이다.


🚀 배열의 요소를 새로운 값으로 변환하는 방법

map


class Prices {
  constructor(name, price){
    this.name = name;
    this.price = price;
  }
}

const price = [
  new Prices ('apple',3000),
  new Prices ('melon',4500),
  new Prices ('grape',5200),
];


const thePriceContainer = price.map(function(eachPrice){
  return eachPrice.price;
}); 

console.log(thePriceContainer); // [3000, 4500, 5200]

let priceMultiply = price.map(function(multiplePrices) {
  return multiplePrices.price * 2;
});

console.log(priceMultiply); // [6000, 9000, 10400]

✔️ map은 배열 내 요소들을 새로운 값의 묶음으로 변환하여 출력 해준다.

  • 위 첫 번째 코드를 살펴 보면, thePriceContainer라는 변수 내에 price.map이라는 메소드를 사용하여 콜백 함수를 넘겨주고, 그 콜백 함수를 통해 각 과일들의 'price' 부분에만 접근하고 있다.
    출력해보면, 과일의 가격 값들만 들어 있는 배열이 출력된다.

  • 두 번째 코드를 살펴 보면, priceMultiply라는 변수 내에 마찬가지로 price.map을 통해 콜백 함수를 넘겨주고, 각 과일들의 'price'에 곱하기 2를 해주고 있다.
    출력해보면, 과일들의 가격에 각각 2가 곱해진 후 배열로 출력된 것을 알 수 있다.

즉, 'map'을 사용하면 배열 내 모든 요소들은 콜백 함수를 통해, 콜백 함수에서 리턴 된 값으로 대체되게 된다.


🚀 특정 조건의 만족 여부를 검사하는 방법

some

class Score {
  constructor(name, score){
    this.name = name;
    this.score = score;
  }
}

const scoresList = [
  new Score ('현수', 98),
  new Score ('민형', 78),
  new Score ('수찬', 85),
];


const test = scoresList.some(function(eachScore){
  return eachScore.score > 90;
});

console.log(test); // true

✔️ some은 배열 내 요소들 중 특정 조건을 만족하는 요소가 있는 지 없는 지 검사한다. 만약 있다면 true, 없으면 false를 출력한다.

위 코드를 보면 학생들의 점수가 90점이 넘는 지 아닌 지 확인하는 조건이 있고, 학생들의 점수를 살펴 보면 '현수'가 90점이 넘는다. 따라서 true가 출력된다.

every

class Score {
  constructor(name, score){
    this.name = name;
    this.score = score;
  }
}

const scoresList = [
  new Score ('현수', 98),
  new Score ('민형', 78),
  new Score ('수찬', 85),
];


const test = scoresList.every(function(eachScore){
  return eachScore.score > 90;
})

console.log(test); // false

✔️ every는 some과는 다르게, 주어진 조건을 요소들이 모두 만족해야만 true가 출력된다. 따라서, '현수'는 90점이 넘지만 '민형', '수찬'은 넘지 않기 때문에 결과적으로 false가 출력되는 것이다.


🚀 배열 요소들의 누적 값을 출력하는 방법

reduce

class Score {
  constructor(name, score){
    this.name = name;
    this.score = score;
  }
}

const scoresList = [
  new Score ('현수', 98),
  new Score ('민형', 78),
  new Score ('수찬', 85),
  new Score ('유성', 56),
];


const accumulatedScore = scoresList.reduce(function(pr,cur){
  return pr + cur.score;
},0);

console.log(accumulatedScore); // 317

✔️ reduce는 이전 값 (previous)과 현재 값 (current) 값을 받아온다. 따라서 이 값을 더할 수도, 각각의 값만 출력 할 수도 있다.

따라서 reduce의 콜백 함수의 인자로는 이전 값, 그리고 현재 값을 의미하는 parameter가 필요하다.

위 예시는 각 학생들의 점수를 모두 더한 결과를 출력한다.
pr, cur를 콜백 함수의 인자로 넘겨주고, 각각의 값을 더한다. 이 때, 이전 값의 시작을 0으로 하기 위해 함수 끝 부분에 0을 주었다.


🤯 위 로직이 이해가 안가고 어려울 수 있다.
쉬운 이해를 위해, 예시를 조금 더 들어보도록 하자.

(console 작성 시 편의를 위해 let을 사용 했다)

위 로직에서 pr 값만 출력 시, 첫 번째 배열 값인 '현수'에 대한 정보가 출력된다.

그리고 cur 값만 출력 시, 마지막 배열 값인 '유성'에 대한 정보가 출력된다.

우선 위 정보를 통해, 현재 pr -> 현수, cur -> 유성에 대한 정보라는 사실을 파악했다.

❓ 만약 이 상태에서 pr.score에 접근하려고 한다면? TypeError가 발생한다.
콜백 함수를 통해 받아온 pr의 score가 아직 없기 때문이다.

그렇다면 cur.score 시에는? 유성의 점수 값인 56이 출력된다.

즉, pr에는 직접 우리가 값을 넘겨주고, cur을 통해서 원하는 값을 출력할 수 있도록 로직을 구성해주면 되는 것이다.

따라서 위 예시처럼 먼저 0이라는 최초 값을 할당해주고, 그 뒤에 cur.score를 통해서 값에 접근하면,

1️⃣ 첫 번째 pr: 0, cur: 0
2️⃣ 두 번째 pr: 98, cur: 0 + 98
3️⃣ 세 번째 pr: 78, cur: 0 + 98 + 78
4️⃣ 네 번째 pr: 85, cur: 0 + 98 + 78 + 85
5️⃣ 다섯 번째 pr: 56, cur: 0 + 98 + 78 + 85 + 56 = 317

최종적으로 317이 출력되는 것이다.


🚀 배열 요소의 순서를 결정하는 방법

sort


const numbers = [20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

const sortNumbers = numbers.sort(function(a, b){
  return a - b;
});

console.log(sortNumbers.join(',')); // '1,2,3,4,5,6,7,8,9,10,20'

✔️ sort는 요소의 순서를 결정할 때 사용한다.

오름차순, 내림차순으로 요소의 순서를 출력할 수 있으며, 숫자 뿐만 아니라 문자열 또한 순서를 정렬할 수 있다.

위 예시에서는 sort의 콜백 함수 인자로 a, b를 주었으며 a-b의 조건을 주었다. 만약 b-a로 조건을 준다면 내림차순의 형태로 출력이 될 것이다.

sort를 통해 정렬한 배열의 값을 join 메소드를 통해 문자열로 출력했다.
다양한 배열 API들을 조합하여 쓸 수도 있다!


✨ TIL을 마무리하며

개인적으로 자바스크립트 문제를 풀거나, 과제를 해 나갈 때 배열에 대한 부분이 약하다고 느꼈다. 따라서 다양한 배열 API들에 대해 다시 한 번 정리하고 공부하면서 적재적소에 적용해보고 싶다는 생각이 들었다.

특히 reduce나 map의 경우 나에게 다소 생소해서 자주 활용하지 못했는데, 이후로는 잘 활용해보아야 겠다는 생각이 든다. 잘만 활용하면 짧은 코드로, 쉽고 간결하게 원하는 로직을 구성할 수 있을 것 같다.

이번 글은 아무래도 분량이 많은 만큼 시간이 오래 걸렸다.. 힘들었다..😂
하지만 input = output. 투자한 시간만큼 나에게 돌아오는 것도 클 것이다.
앞으로도 화이팅!

profile
나만의 세상을 개척하고 싶은 사람

2개의 댓글

comment-user-thumbnail
2021년 6월 17일

지현님 정리는 정말 대박 ...

1개의 답글