TIL#8 JS) Array Methods

luneah·2021년 10월 30일
0

JavaScript

목록 보기
8/16
post-thumbnail

배열의 메소드

.slice()

  • 원본 배열의 복사본을 새로운 배열 객체로 반환하는 메소드.
  • 새로운 배열 객체를 만들기 때문에, 다른 변수를 꼭 할당해야 함.
  • 이때 원본 배열은 변하지 않는다.

.slice(시작 인덱스, 끝 인덱스);
여기선 인자 2개가 들어갔지만, slice 메소드는 필요에 따라 인자를 최소 1개만 쓸 수도 있다.

  • 첫번째 인자 : 배열의 index의 시작점
  • 두번째 인자 : 배열의 index의 끝점
  • 시작 인덱스부터 끝 인덱스의 까지 복제
  • 끝 인덱스가 음수일 경우, 배열의 끝에서부터 앞까지 차례대로 -1, -2, -3 ... 순
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
                        // [-3][-2][-1]

let arr1 = arr.slice(3, 5);  // [3]부터 [4]까지 
console.log(arr1);           // [4, 5]

let arr2 = arr.slice(-1);    // 배열의 제일 끝 요소부터 리턴
console.log(arr2);           // [9]

let arr3 = arr.slice(0, -2); // [0]부터 [-2] 앞까지
console.log(arr3);           // [1, 2, 3, 4, 5, 6, 7]

let arr4 = arr.slice(-2);    // 배열의 제일 끝 요소부터 그 이전까지만 리턴
console.log(arr4);           // [8, 9]

다차원배열 예제

function saveNumberTwo(prisoners) {
  let temp = prisoners.slice(-2);  // [[1,2], [0,0]]
  let answer = temp[0][1];         // temp[0]=[1,2] 중에서도 인덱스[1]=2
  
  return answer;  // 2
}

let prisoners = [[0, 1],[1,2],[0,0]];
saveNumberTwo(prisoners);   // 2

.splice()

  • 원본 배열 객체를 직접 수정하는 메소드.
  • 지울 원소 개수, 추가할 원소들을 받아서 사용함.
  • 이때 원본 배열 객체는 변한다.

.splice(수정할 인덱스 번호, 삭제할 인덱스 원소 개수, 배열에 추가할 요소)
ex: arr.splice(5, 3, 'Hello', 'banana');

  • 인덱스 [5]부터 변경이 됨.
  • [5]의 다음 요소 3개가 삭제가 됨.
  • [5]의 다음 요소부터 "Hello", "banana" 의 원소가 추가 됨.
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

arr.splice(5, 3, 'apple', 'banana');
// 인덱스 [5]부터 요소 3개를 제거 후, 'apple'과 'banana'를 추가

console.log(arr);
// [1, 2, 3, 4, 5, "apple", "banana", 9]
// [0][1][2][3][4]

요소 삭제, 삭제 후 변경하고 싶을 때의 예제

let myArr = ['사과', '빵', '우유', '과자', '감자'];
// '우유'를 삭제하고 싶음

myArr.splice(2, 1);  // 인덱스 [2]부터 요소 1개를 제거

console.log(myArr);  // ['사과', '빵', '과자', '감자']
let myArr = ['사과', '빵', '우유', '과자', '감자'];
// '우유'를 '두유'로 바꾸고 싶음

myArr.splice(2, 1, '두유'); // 인덱스 [2]부터 요소 1개를 제거하고, '두유'로 변경

console.log(myArr);        // ['사과', '빵', '두유', '과자', '감자']

.filter() : 걸러내기

  • 배열을 순회하며 요소마다 조건 확인 후, 조건을 만족하는 원소들로 구성된 새로운 배열을 리턴하는 메소드.
  • 배열에 조건을 주어, 조건에 만족하지 않는 요소를 걸러낸다.
  • 조건에 부합되는 요소가 없다면 빈 배열을 반환한다.

let newArr = arr.filter(callback(currentValue[element, index, [array]]) {
}[, thisArg]);

  • callback : 3개의 인자 (element, index, array) 를 가지는 조건값에 대한 함수
  • element : 처리할 현재 요소
  • index : 현재 인덱스
  • array : filter를 호출한 배열
  • thisArg : callback을 생행 할 때 this로 사용하는 값
let numbers = [10, 4, 32, 17, 5, 2];

let result = numbers.filter((value)=> value > 10); // 10보다 큰 원소만 골라서 새로운 배열을 리턴

console.log(result); // [32, 17]

💡 .filter()안에 들어간 변수명(value)은 임의로 지어도 됨.


.includes()를 활용한 .filter 콜백함수 예제

Q. fruits 라는 배열이 있다. 'ap'가 들어간 과일들로 이루어진 새로운 배열을 filter()를 이용하여 반환하라. 결과는 아래와 같아야 한다.

[ 'apple', 'grapes' ]

🔥 My Answer

  1. filter()의 인자에서 바로 함수를 써주는 방법
function filtered(value) {

  return fruits.filter(value => value.includes('ap'));
}
console.log(filtered());

▶ Feedback
let result 선언해서 푸는 것이 깔끔함.

  1. 밖에서 함수를 선언하고 filter() 인자에서 callback하는 방법

Try 1)

오답

function filtered (value) {
  return value.includes('ap');
}

let result = fruits.filter(filtered);

console.log(result);   // 출력 자체는 정상 ['apple', 'grapes']

▶ Feedback
문제 의도 파악 miss: includes()를 이용해 'ap'포함된 과일을 filter 메소드를 이용해서 return 하길 원하는 것
Sol ) 함수 코드 블럭 안에서 return 해주기 위해 filter를 이용한 구문도 함수 안으로 들어가야 함.

Try 2)

function filtered () {
  let result = fruits.filter(includeAp)
  return result
}

function includeAp(texts){
  return texts.includes("ap")
}
console.log(filtered());

▶ Feedback
filter 메소드 안의 함수를 밖으로 빼버리는 방법으로 작동 문제는 없으나 가독성 떨어짐.
Sol) callback 호출 사용하여 깔끔하게 정리

🔥 Model Answer

  • 1번 방법
function filtered () {
  let result = fruits.filter((value) => value.includes('ap'));
  
  return result;
}

console.log(filtered());   // expected output: ["apple", "grapes"]
  • 2번 방법
function filtered(value) {   // 2 - Arr 배열의 복제본이 함수에 전달
   let value2 = value.includes('ap');   // 3 - 복제본의 원소들 중 'ap'가 포함된 문자열 검색하여 새로운 변수 value2에 담는다
   return value2;    // 4 - 새로운 변수 value2 리턴
}

let result = Arr.filter(filtered);  // 1 - filter()를 이용하여 콜백함수 호출 -> 리턴된 value2 값을 새로운 변수 result에 담는다

console.log(result);   // 5 - result값 반환

.includes() : 배열 탐색하기

  • 배열 속 해당 요소가 있으면 true, 없으면 false를 반환하는 메소드.

arr.includes(valueToFind[, fromIndex]);

매개변수

  • valueToFind : 탐색할 요소
    *참고: 문자나 문자열을 비교할 때, includes()는 대소문자를 구분함.
  • fromIndex (Optional) : 배열에서 searchElement 검색을 시작할 위치.
    음의 값은 array.length + fromIndex의 인덱스를 asc로 검색. 기본값 : 0
var a = [1, 2, 3, 4, 5, 1, 2, 3];

var b = a.includes(3); // 배열 a에 3이 있는지 T/F
console.log(b);        // true

var c = a.includes(6); // 배열 a에 6이 있는지 T/F
console.log(c);        // false

[1, 2, 3].includes(3, -1); // true
[1, 2, NaN].includes(NaN); // true

.indexOf() : 배열 탐색하기

  • 찾은 값의 첫 번째 원소의 위치(=인덱스)를 반환하는 메소드.
  • 중복된 값이 뒤에 있어도, 무조건 첫 번째 원소의 인덱스를 반환한다.
  • 찾고 싶은 값이 그 배열에 없다면 -1을 반환한다.

arr.indexOf(searchElement[, fromIndex]);

매개변수

  • searchElement : 배열에서 찾을 요소
  • fromIndex (Optional) : 검색을 시작할 인덱스
    인덱스가 배열의 길이보다 크거나 같은 경우 -1이 반환되므로 배열이 검색되지 않음. 제공된 인덱스 값이 음수이면 배열 끝에서부터의 오프셋 값으로 사용됨.
    *참고 : 제공된 인덱스가 음수이면 배열은 앞에서 뒤로 검색됨. 계산된 인덱스가 0보다 작으면 전체 배열이 검색됨. 기본값 : 0 (전체 배열 검색)

.concat() : 합치기

  • 인자로 주어진 배열이나 값들을 기존 배열에 합쳐서 새 배열을 반환하는 메소드.
  • 기존 배열을 변경하지 않는다.
  • 추가된 새로운 배열을 반환한다.

array.concat([value1[, value2[, ...[, valueN]]]]);

  • 배열 또는 값
  • 만약 value1 ~ valueN 인자를 생략하면 기존 배열의 얕은 복사본을 반환.
  • valueN (optional)
    *참고: 배열이나 값을 이어붙여도 원본은 변하지 않으며, 새로운 배열이나 원본 배열을 조작해도 서로 영향을 받지 않습니다.
const alpha = ['a', 'b', 'c'];

// 배열 2개 이어붙이기 
const arr = [1, [2, 3]];     
alpha.concat(arr);             // [ 'a', 'b', 'c', 1, [ 2, 3 ] ]

// 배열 3개 이어붙이기 
alpha.concat(arr);
alpha.concat(1, [2, 3]);       // [ 'a', 'b', 'c', 1, 2, 3 ]

// 중복된 숫자나 글자를 가진 배열을 합칠 때 --> 요소의 중복과 상관없이 배열 합쳐줌.
const numbers = [1, 2, 3];
const numbers2 = [3, 4, 5];

numbers.concat(numbers2);      // [ 1, 2, 3, 3, 4, 5 ]

.filter() 활용한 .concat 예제

Q. 파스타와 피자의 재료가 배열로 나타나있다. 중복된 재료를 뺀 전체 재료의 배열 한 개를 만들어라. 결과는 아래와 같아야 한다.

// 중복된 재료를 뺀 전체 재료
[ 'tomato', 'basil', 'onion', 'chicken', 'cheese', 'olive', 'beef' ]

🔥 My Answer

오답

let pasta = ['tomato', 'basil', 'onion','chicken'];
let pizza = ['tomato', 'cheese', 'onion','olive','beef'];

function totalIngredients () {
  let result = pasta.concat(pizza);

  let erase = result.filter(('tomato', 0) => result.indexOf('tomato') === 0);
}
console.log(totalIngredients());

▶ Feedback
arrow function 사용 miss, return 사용 안 함.
Sol ) let 사용해서 새로운 변수 선언해주고 result.filter((el,index) =>
result.indexOf(el) === index) 사용해야 함.

🔥 Model Answer

let pasta = ['tomato', 'basil', 'onion','chicken'];
let pizza = ['tomato', 'cheese', 'onion','olive','beef'];

function totalIngredients () {
  let result = pasta.concat(pizza);
    let newResult = result.filter((word, index) => 
    result.indexOf(word) === index);

  return newResult;
}
console.log(totalIngredients());

Set 객체

  • 자료형에 관계 없이 원시 값과 객체 참조 모두 유일한 값을 저장할 수 있다.
  • 요소의 값이 유일하기 위해 검사를 수행하기 때문에 중복된 값을 제거하고 싶을 때 사용한다.
  • 새로운 Set 객체를 반환한다.

new Set([iterable]);

매개변수

  • iterable : 반복 가능한 객체가 전달된 경우, 그 요소는 모두 새로운 Set에 추가됨. 만약 매개변수를 명시하지 않거나 null을 전달하면, 새로운 Set은 비어 있는 상태가 됨.
// array 의 경우 문제 없다.
let employeeId = ['a12', 'e7', 'c2', 'a12'];

// set은 각 요소가 유일해야 한다.
let employeeId2 = new Set(['a12', 'e7', 'c2', 'a12']);
console.log(employee2); // {'a12', 'e7', 'a12'}

Set 메소드

.size : array의 length와 동일
.add : array의 push와 동일 * 참조형 데이터는 동일한 요소 추가 가능
.clear : empty the Set
.delete : 특정 요소를 삭제
.entries : Map처럼, iterable을 반환한다. key-value pair를 반환하지만 key와 value는 같다.
.forEach
.has : 특정 요소가 존재하는지 확인한다.
.keys, .values


Array 반복문으로 사용되는 메소드

arrow function을 가장 많이 사용할 때는 callback 함수로 사용할 때다. callback 함수는 인자로 전달되는 함수를 의미한다. array 반복문으로 사용되는 메서드로는 map과 forEach가 있다.

.map() : 변경하기

  • 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출(callback)한 결과를 모아 새로운 배열을 반환하는 메소드.

arr.map(callback(currentValue[, index[, array]])[, thisArg]);

매개변수

  • callback : 새로운 배열 요소를 생성하는 함수
  • currentValue : 처리할 현재 요소
  • index (optional) : 처리할 현재 요소의 인덱스
  • array (optional) : map()을 호출한 배열
  • thisArg (optional) : callback을 실행할 때 this로 사용되는 값
var array = [1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1, 9.1, 10.1];

// 일반함수로 map 메서드 표현
var array10 = array.map(function (elements){
  return elements * 10;
});

console.log(array10);
// [11, 21, 31, 41, 51, 61, 71, 81, 91, 101]

// 화살표함수로 map 메서드 표현
var array20 = array.map((el) => el*10);

console.log(array20);
// [11, 21, 31, 41, 51, 61, 71, 81, 91, 101]

💡 map VS filter
공통점: 기존 배열은 건드리지 않고 요소들을 순회한 후 새로운 배열을 리턴하는 메소드
차이점: map은 콜백 함수가 적용된 새 요소, filter는 조건문을 만족한 요소들을 반환

.forEach()

  • 주어진 함수를 배열 요소 각각에 대해 실행하는 메소드.

arr.forEach(callback(currentvalue[, index[, array]])[, thisArg]);

매개변수

  • callback : 각 요소에 대해 실행할 함수
  • currentValue : 처리할 현재 요소
  • index (optional) : 처리할 현재 요소의 인덱스
  • array (optional) : forEach()를 호출한 배열
  • thisArg (optional) : callback을 실행할 때 this로 사용할 값

forEach는 for 대신 사용하는 반복문이다. map과의 큰 차이는 map이 요소가 수정된 새로운 배열이 return되었다면, forEach아무것도 return하는 것이 없다. 그래서 forEach로 전달되는 callback 함수에서도 return하는 것이 없다.

let startWithNames = [];
let names = ['a', 'ab', 'cbb', 'ada'];

names.forEach(el => {   
  if (el.startsWith('a')) {     
    startWithNames.push(el);   
  } 
});
let hasC = false;
let arr = ['a', 'b', 'c', 'd'];

arr.forEach(el => {
  if (el === 'c') {
    hasC = true;
    return;
  }
});

forEach도 함수이므로, 중간에 반복문을 탈출하고 싶으면 return; 을 해주면 된다. 만약 forEach에서 현재 index를 알고 싶으면 두 번째 인자로 받을 수 있다.

let idxOfC = -1;
let arr = ['a', 'b', 'c', 'd'];

arr.forEach((el, idx) => {
  if (el === 'c') {
    idxOfC = idx;
    return;
  }
});
profile
하늘이의 개발 일기

0개의 댓글