자료구조와 자료형 : 배열과 메서드

라용·2022년 11월 27일
0

모던 JavaScript 튜토리얼 내용 중 일부 문제를 정리한 내용입니다.

배열 요소 추가, 제거

splice

배열의 요소를 추가, 삭제, 교체하고 싶다면 splice 메서드를 사용합니다.

arr.splice(index[, deleteCount, elem1, ..., elemN])

index 는 조작을 가할 첫 번째 요소를 가리키고, deleteCount 는 제거하려는 요소의 개수를 나타냅니다. elem1, ..., elemN 은 배열에 추가할 요소를 나타냅니다. 기존 배열은 수정되고, splice 자체는 삭제된 요소로 구성된 배열을 반환하니 유의합니다.

// 기존 배열의 요소를 제거

let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); 
alert( arr ); // ["I", "JavaScript"]

// splice 자체는 삭제된 요소를 배열로 반환 

let arr = ["I", "study", "JavaScript", "right", "now"];
let removed = arr.splice(0, 2);
alert( removed ); // "I", "study" 

// 삭제하고 추가하는 경우

let arr = ["I", "study", "JavaScript", "right", "now"];
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // ["Let's", "dance", "right", "now"]

// 삭제하지 않고 추가하는 경우, 두번째 인자 0으로

let arr = ["I", "study", "JavaScript"];
arr.splice(2, 0, "complex", "language");
alert( arr ); // "I", "study", "complex", "language", "JavaScript"

slice

arr.slice 는 arr.splice 와 유사하지만 더 간단합니다.

arr.slice([start], [end])

start 인덱스 부터 end 인덱스 앞까지의 요소를 복사한 새로운 배열을 반환합니다. arr.slice() 처럼 인수에 값을 넣지 않고 arr 의 복사본을 만들면, 기존 배열을 건드리지 않고 새로운 배열을 만들 수 있습니다.

let arr = ["t", "e", "s", "t"];
let newArr = arr.slice() // 복사본 새로운 배열로 생성

alert( arr.slice(1, 3) ); // e,s 
alert( arr.slice(-2) ); // s,t 음수일 경우 배열 끝에서부터 요소 개수 셈

concat

arr.concat 은 기존 배열의 요소를 사용해 새로운 배열을 만들거나 기존 배열에 요소를 추가할 때 사용합니다.

arr.concat(arg1, arg2 ...) 

arr 의 모든 요소와 argN 에 속한 모든 요소가 모여 새로우 배열이 반환됩니다. 배열이 들어온다면 모든 요소가 복사되고 객체를 인자로 받으면 객체가 통으로 복사됩니다.

let arr = [1, 2];

alert( arr.concat([3, 4]) ); // 1,2,3,4
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

// 객체의 경우 분해되지 않고 결합

let arr = [1, 2];
let arrayLike = {
  0: "something",
  length: 1
};

alert( arr.concat(arrayLike) ); // 1,2,[object Object]

밸로퍼트 모던 리액트 예제에서는 아래와 같이 사용합니다.

const [users, setUsers] = useState([
  {
    id: 1,
    username: 'velopert',
    email: 'public.velopert@gmail.com',
    active: true,
  },
]);

..

const onCreate = () => {
  const user = { // 사용자가 입력한 새로운 객체
    id: nextId.current,
    username,
    email,
  };
  setUsers(users.concat(user)); // 여기서 사용
};

forEach 반복작업

arr.forEach 는 배열 요소를 순회하며 주어진 함수를 실행합니다.

// 기본 형태

arr.forEach(function(item, index, array) {
  // 요소에 무언가를 할 수 있습니다.
});

// 값을 출력해본다면,

["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
  alert(`${item} is at index ${index} in ${array}`);
});

배열 탐색

indexOf, lastIndexOf 와 includes

arr.indexOf(item, from) 은 인덱스 from 부터 시작해 item 을 찾아, 해당 요소의 인덱스를 반환합니다. 발견하지 못하면 -1 을 반환합니다. arr.lastIndexOf(item, from) 은 같은 기능을 수행하는데 검색을 끝에서 부터 합니다. arr.includes(item, from) 은 from 부터 시작해 Item 이 있는지 검색하고 있으면 true 없으면 false 를 반환합니다. 요소가 배열 내 존재하는지 여부만 확인한다면 Includes 를 사용하는 게 좋습니다.

let arr = [1, 0, false];

arr.indexOf(0); // 1
arr.indexOf(false); // 2 -- 완전 항등 연산자 === 로 비교, falsy 한 값이 아닌 false 체크
arr.indexOf(null); // -1

arr.includes(1); // true

find, findIndex

특정 조건에 맞는 배열 내 객체를 찾고 싶다면 arr.find 를 사용합니다.

let result = arr.find(function(item, index, array) {
  // true가 반환되면 반복이 멈추고 해당 요소를 반환
  // 조건에 해당하는 요소가 없으면 undefined를 반환
});

함수는 배열의 요소를 받아 조건식으로 true 이면 해당 요소를 반환합니다. 해당 요소가 없으면 undefined 입니다. 아래 예시는 배열 내 id == 1 조건을 충족하는 사용자 객체를 찾습니다. 해당 id 를 찾으면 탐색을 중단합니다. id 값이 1 이 이후에 있어도 처음 찾은 값만 반환합니다.

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

let user = users.find(item => item.id == 1);

alert(user.name); // John

위와 같이 find 메서드를 사용하는 경우가 많으며, 두세번째 인자를 쓰는 경우는 별로 없습니다. findIndex 는 비슷하나 해당 요소가 아닌 해다 요소의 인덱스 값을 반환합니다.

filter

find 는 조건에 맞는 요소를 하나만 찾아내지만 filter는 여러개 요소를 모두 찾습니다. filter 는 조건에 맞는 요소 전체를 담은 배열을 반환합니다.

let results = arr.filter(function(item, index, array) {
  // 조건을 충족하는 요소는 results에 순차적으로 더해짐
  // 조건을 충족하는 요소가 하나도 없으면 빈 배열이 반환
});

// 예시

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

// 앞쪽 사용자 두 명 반환
let someUsers = users.filter(item => item.id < 3);

someUsers.length; // 2

배열 변형

map

arr.map 은 사용 빈도가 높은 메서드입니다. 배열 요소 전체를 대상으로 함수를 호출하고, 그 결과를 새로운 배열로 반환합니다.

let result = arr.map(function(item, index, array) {
  // 요소 대신 새로운 값을 반환
});

// 문자열 길이를 출력해서 배열로 반환

let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
lengths; // [5,7,6]

sort

arr.sort() 는 배열 요소를 정렬합니다. 이때 기존 배열 자체가 변경되며 재정렬된 배열 자체도 반환됩니다. sort 를 그대로 사용하면 문자열의 경우 사전편집 순으로 비교되어서 2가 15보다 크다고 취급됩니다. 새로운 정렬 기준을 적용하려면 arr.sort() 에 새로운 함수를 전달해야합니다. 아래는 숫자 오름차순 기준의 정렬입니다.

function compareNumeric(a, b) {
  if (a > b) return 1;
  if (a == b) return 0;
  if (a < b) return -1;
}

let arr = [ 1, 2, 15 ];
arr.sort(compareNumeric);

alert(arr);  // 1, 2, 15

// 양수를 반환하고 싶다면 아래처럼 첫번째 인수가 두번째 인수보다 크다고만 표현해도 됩니다.

let arr = [ 1, 2, 15 ];
arr.sort(function(a, b) { return a - b; });

// 화살표 함수르 사용하면 더 깔끔

arr.sort( (a, b) => a - b );

reavese

arr.reverse 는 arr 요소를 역순으로 정렬합니다.

let arr = [1, 2, 3, 4, 5];
arr.reverse();

arr; // 5,4,3,2,1

split, join

str.split(delim) 은 구분자 delim 을 기준으로 문자열을 쪼개서 배열에 담아줍니다. str.join은 그 반대 역할을 합니다.

let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');

arr; // [Bilbo, Gandalf, Nazgul]

// 문자열을 글자 단위로 분리할 수도 있음

let str = "test";
str.split(''); // t,e,s,t

// join 은 반대 역할

let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str = arr.join(';');

alert( str ); // Bilbo;Gandalf;Nazgul

reduce

배열 기반으로 값 하나를 도출할 때 사용합니다.

let value = arr.reduce(function(accumulator, item, index, array) {
  // ...
}, [initial]);

인수로 넘겨주는 함수는 배열의 모든 요소를 대상으로 적용되며 적용 졀과는 다음 함수 호출시 사용됩니다. accumulator 는 이전 함수의 호출결과이고 initial 은 함수 최초 호출 시 초깃값입니다.

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

let result = arr.reduce((sum, current) => sum + current, 0); // 초기 값 0 생략 가능

alert(result); // 15

reduce 는 보통 위 예제처럼 두개 인수를 받습니다. 함수 최초 호출 시 초기값 0 이 sum 에 할당되고 current 에는 배열 첫번째 요소 1이 할당됩니다. 두번째 호출에는 sum = 1 에 배열 두번째 요소 2가 더해져 3이 되고, 다음에는 3에 다음 요소가 더해집니다. 초기 값 0을 생략해도 되는데 그럴 경우 첫번째 값에 배열의 첫 번째 요소를 사용합니다. 이럴 경우 배열이 비어있다면 에러가 발생하니 주의해야 합니다.

Array.isArray 배열 여부 확인

배열은 객체형에 속하므로 typeof 로 구분할 수 없습니다. 이럴 때 Array.isArray() 를 사용하면 배열 여부를 확인할 수 있습니다.

alert(typeof {}); // object
alert(typeof []); // object

alert(Array.isArray({})); // false
alert(Array.isArray([])); // true

배열 메서드, thisArg

thisArg 는 선택적으로 사용할 수 있는 마지막 인수입니다.

arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);

아래처럼 this 를 사용한 함수를 호출하는 경우 해당 this 에 해당하는 값을 넣어주어야 에러를 방지할 수 있습니다.

let army = {
  minAge: 18,
  maxAge: 27,
  canJoin(user) {
    return user.age >= this.minAge && user.age < this.maxAge;
  }
};

let soldiers = users.filter(army.canJoin, army);
profile
Today I Learned

0개의 댓글