[K.O Javascript] 자료구조와 자료형 - 배열 및 배열과 메서드

진형욱·2022년 8월 9일
0

TIL - JavaScript

목록 보기
5/6
post-thumbnail

배열

순서가 있는 컬렉션을 저장할 때 쓰는 자료구조인 배열을 알아보자

배열 선언

let arr = new Array();
let arr = [];
  • 대부분 두번째 방법으로 배열을 선언한다.

예시

let fruits = ["사과", "오렌지", "자두"];

배열 요소 수정

fruits[2] = '배'; // 배열이 ["사과", "오렌지", "배"]로 바뀜

배열 요소 추가

fruits[3] = '레몬'; // 배열이 ["사과", "오렌지", "배", "레몬"]으로 바뀜

배열 요소 길이 확인 (length 사용)

let fruits = ["사과", "오렌지", "자두"];

alert( fruits.length ); // 3

배열 요소의 자료형엔 제약이 없다.

// 요소에 여러 가지 자료형이 섞여 있습니다.
let arr = [ '사과', { name: '이보라' }, true, function() { alert('안녕하세요.'); } ];

// 인덱스가 1인 요소(객체)의 name 프로퍼티를 출력합니다.
alert( arr[1].name ); // 이보라

// 인덱스가 3인 요소(함수)를 실행합니다.
arr[3](); // 안녕하세요.

trailing 쉼표 : 배열의 마지막 요소는 객체와 마찬가지로 쉼표로 끝날 수 있습니다.


큐 와 스택

배열을 사용해 만들 수 있는 대표적인 자료구조

  • push : 맨 끝에 요소를 추가한다.

  • shift : 제일 앞 요소를 꺼내 제거한 후, 남아있는 요소를 앞으로 밀어준다.

    • unshift : 배열 앞에 요소를 추가한다.

- unshift의 예시

let fruits = ["오렌지", "배"];
fruits.unshift('사과');
alert( fruits ); // 사과,오렌지,배

배열엔 두 연산을 가능하게 해주는 내장 메서드 pushpop이 있다.
화면에 순차적으로 띄울 메시지를 비축해 놓을 자료 구조를 만들 때 를 사용하는 것처럼
는 실무에서 상당히 자주 쓰이는 자료구조이다.

스택

배열은 큐 이외에 스택(stack)이라 불리는 자료구조를 구현한다.

  • push : 요소를 스택 끝에 집어 넣는다.
  • pop : 스택 끝 요소를 추출한다.

스택은 이처럼 '한쪽 끝'에 더하거나 뺄 수 있게 해주는 자료구조이다.

스택을 사용하면 가장 나중에 집어넣은 요소가 먼저 나온다. 이런 특징을 LIFO이라 부른다.

반면 를 사용하면 먼저 집어넣은 요소가 먼저 나오기 때문에, 이런 특징을 FIFO 자료구조라 부른다.

이렇게 처음이나 끝에 요소를 더하거나 빼주는 연산을 제공하는 자료구조를 데큐라고 부른다.

성능 : push와 pop은 빠르지만 shift와 unshift는 느립니다.


반복문

for문

for문은 배열을 순회할때 쓰는 가장 오래된 방법이다.

let arr = ["사과", "오렌지", "배"];

for (let i = 0; i < arr.length; i++) {
  alert( arr[i] );
}

length

배열에 무언가 조작을 가하면 length프로퍼티가 자동으로 갱신된다.

length프로퍼티는 배열 내 요소의 개수가 아니라 가장 큰 인덱스에 1을 더한 값이다.

length프로퍼티의 또 다른 특징은 쓰기가 가능하다는 점이다.

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

arr.length = 2; // 요소 2개만 남기고 잘라봅시다.
alert( arr ); // [1, 2]

arr.length = 5; // 본래 길이로 되돌려 봅시다.
alert( arr[3] ); // undefined: 삭제된 기존 요소들이 복구되지 않습니다.
  • 이런 특징을 이용하면 arr.length = 0;을 사용해 간단하게 배열을 비울 수 있다.

new Array()

let arr = new Array("사과", "배", "기타");
  • 대괄호 []를 사용하면 더 짧은 문법으로 배열을 만들 수 있어 잘 사용하지 않는다.

다차원 배열

배열 역시 배열의 요소가 될 수 있다. 이런 배열을 다차원 배열이라 부른다.

let matrix = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];
alert( matrix[1][1] ); // 5, 중심에 있는 요소

요약

배열

배열은 특수한 형태의 객체로, 순서가 있는 자료를 저장하고 관리하는 용도이다.

- 선언 방법 :

// 대괄호 (가장 많이 쓰이는 방법임)
let arr = [item1, item2...];

// new Array (잘 쓰이지 않음)
let arr = new Array(item1, item2...);
  • new Array(number)을 호출하면 길이가 number인 배열이 만들어지는데 이 때 요소는 비어있다.

  • lenght 프로퍼티는 배열의 길이를 나타내준다. 정확히는 숫자형 인덱스 중 가장 큰 값에 1을 더한 값이다.

  • length 값을 수동으로 줄이면 배열 끝이 잘린다.

데큐

  • push(...items) – items를 배열 에 더해줍니다.

  • pop() – 배열 요소를 제거하고, 제거한 요소를 반환합니다.

  • shift() – 배열 처음 요소를 제거하고, 제거한 요소를 반환합니다.

  • unshift(...items) – items를 배열 처음에 더해줍니다.


배열과 메서드

요소 추가/제거 메서드

배열의 맨 앞이나 끝에 요소를 추가하거나 제거하는 메서드 (push,pop,shift,unshift) 는 위에 학습을 했고 이외 요소 추가와 제거에 관련된 메서드를 알아보자.

splice

배열에서 요소 하나만 지우고 싶다면 배열 역시 객체형에 속하므로 프로퍼티를 지울때는 연산자 delete를 사용할 수 있다.

let arr = ["I", "go", "home"];

delete arr[1]; // "go"를 삭제합니다.

alert( arr[1] ); // undefined

// delete를 써서 요소를 지우고 난 후 배열 --> arr = ["I",  , "home"];
alert( arr.length ); // 3

요소를 지우긴 했지만 여전히 배열의 요소는 3개이다.

delete obj.keykey를 이용해 해당 키에 상응하는 값을 지우기 때문에 요소의 길이가 빈 값으로 남게 되는것이다.

arr.splice(start)는 요소를 자유자재로 다룰 수 있다. 이 메서드를 사용하면 요소 추가, 삭제, 교체 모두 가능하다.

splice 문법

arr.splice(index[, deleteCount, elem1, ..., elemN])
  • index : 조작을 가할 첫 번째 요소를 가리킨다.
  • deleteCount : 제거하고자 하는 요소의 개수를 나타낸다.
  • elem1, ..., elemN : 배열에 추가할 요소를 나타낸다.

예시

let arr = ["I", "study", "JavaScript"];

arr.splice(1, 1); // 인덱스 1부터 요소 한 개를 제거

alert( arr ); // ["I", "JavaScript"]
  • 인덱스 1이 가리키는 요소부터 시작해 요소 한 개를 지웠다.

요소 세 개를 지우고, 그 자리를 다른 요소 두 개로 교체

let arr = ["I", "study", "JavaScript", "right", "now"];

// 처음(0) 세 개(3)의 요소를 지우고, 이 자리를 다른 요소로 대체합니다.
arr.splice(0, 3, "Let's", "dance");

alert( arr ) // now ["Let's", "dance", "right", "now"]

deleteCount0으로 설정해 요소를 제거하지 않고 새로운 요소를 추가

let arr = ["I", "study", "JavaScript"];

// 인덱스 2부터
// 0개의 요소를 삭제합니다.
// 그 후, "complex"와 "language"를 추가합니다.
arr.splice(2, 0, "complex", "language");

alert( arr ); // "I", "study", "complex", "language", "JavaScript"

slice

arr.slice는 arr.splice와 유사해 보이지만 훨씬 간단하다.

slice 문법

arr.slice([start], [end])
  • "start" 인덱스부터 ("end"를 제외한) "end" 인덱스 까지의 요소를 복사한 새로운 배열을 반환한다.
  • arr.slice는 문자열 메서드인 str.slice와 유사하게 동작하는데 arr.slice는 서브 배열을 반환한다.
let arr = ["t", "e", "s", "t"];

alert( arr.slice(1, 3) ); // e,s (인덱스가 1인 요소부터 인덱스가 3인 요소까지를 복사(인덱스가 3인 요소는 제외))

alert( arr.slice(-2) ); // s,t (인덱스가 -2인 요소부터 제일 끝 요소까지를 복사)
  • arr.slice()는 인수를 하나도 넘기지 않고 arr의 복사본을 만들 수 있다.
  • 기존의 배열을 건드리지 않고 배열을 조작해 새로운 배열을 만들고자 할 때 자주 사용된다.

concat

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

concat 문법

arr.concat(arg1, arg2...)
  • 인수엔 배열이나 값이 오는데, 인수 개수에는 제한이 없다.
  • 메서드를 호출시 arr에 속한 모든 요소와 arg1, arg2등에 속한 모든 요소를 한곳에 모은 새로운 배열이 반환된다.
let arr = [1, 2];

// arr의 요소 모두와 [3,4]의 요소 모두를 한데 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4]) ); // 1,2,3,4

// arr의 요소 모두와 [3,4]의 요소 모두, [5,6]의 요소 모두를 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6

// arr의 요소 모두와 [3,4]의 요소 모두, 5와 6을 한데 모은 새로운 배열이 만들어집니다.
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

forEach

arr.forEach는 주어진 함수를 배열 요소 각각에 실행할 수 있게 해준다.

forEach 문법

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

아래는 인덱스 정보까지 더해서 출력해주는 좀 더 정교한 코드이다.

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

결과값
1. Bilbo is at index 0 Bilbo,Gandalf,Nazgul
2. Gandalf is at index 1 Bilbo,Gandalf,Nazgul
3. Nazgul is at index 2 Bilbo,Gandalf,Nazgul


find/findIndex

특정 조건에 부합하는 객체를 배열 내에서 찾는 방법(arr.find(fn))이다.

find와 문법

let result = arr.find(function(item, index, array) {
  // true가 반환되면 반복이 멈추고 해당 요소를 반환합니다.
  // 조건에 해당하는 요소가 없으면 undefined를 반환합니다.
});
  • item : 함수를 호출할 요소
  • index : 요소의 인덱스
  • array : 배열 자기 자신

함수가 참을 반환하면 탐색은 중단되고, 해당 요소가 반환된다.
원하는 요소를 찾지 못했으면 undefined가 반환된다.

idname 프로퍼티를 가진 사용자 객체로 구성된 배열을 예로 들어보자.
(배열 내에서 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
  • (item => item.id == 1).이런 패턴이 가장 많이 사용되는 편이며, 다른 인자들(index, array)은 잘 사용되지 않는다.

  • arr.findIndex는 find와 동일한 일을 하나, 조건에 맞는 요소를 반환하는 대신 해당 요소의 인덱스를 반환한다는 점이 다르다.

    • 조건에 맞는 요소가 없으면 -1이 반환된다.

filter

  • find메서드는 함수의 반환 값을 true로 만드는 단 하나의 요소를 찾는데, 조건을 충족하는 요소가 여러 개라면 arr.filter(fn)을 사용한다.

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);

alert(someUsers.length); // 2

배열을 변형하는 메서드

배열을 변형시키거나 요소를 재 정렬해주는 메서드이다.

map

arr.maap은 유용성과 사용 빈도가 아주 높은 메서드 이다.

map은 배열 요소 전체를 대상으로 함수를 호출하고, 함수 호출 결과를 배열로 반환한다.
map함수 문법:

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

문자열의 길이를 출력해주는 예시

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

sort(fn)

arr.sort()는 배열의 요소를 정리해준다. (배열 자체가 변경된다.)

let arr = [ 1, 2, 15 ];

// arr 내부가 재 정렬됩니다.
arr.sort();

alert( arr );  // 1, 15, 2
  • 요소는 문자열로 취급되어 재 정렬되기 때문에 기대하던 결과(1,2,15)와는 다르게 출력된다.
  • 기본 정렬 기준 대신 새로운 정렬 기준을 만들려면 arr.sort()에 새로운 함수를 넘겨줘야 한다.

reverse

arr.reverse는 arr의 요소를 역순으로 정렬시켜주는 메서드이다.

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

alert( arr ); // 5,4,3,2,1
  • 반환 값은 재 정렬된 배열이다.

Array.isArray

자바스크립트에서 배열은 객체형에 속한다.
따라서 typeof로는 일반 객체와 배열을 구분할 수가 없다.

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

그런데 배열은 자주 사용되는 자료구조라 감별 할 수 있는 메서드가 있다면 아주 유용하다.

Array.isArray(value)는 이럴 때 사용할 수 있는 메서드이다.

  • value가 배열이라면 true를, 배열이 아니라면 false를 반환한다.
alert(Array.isArray({})); // false

alert(Array.isArray([])); // true

요약

요소를 더하거나 지우기

  • push(...items) : 맨 끝에 요소 추가

  • pop() : 맨 끝에 요소 추출

  • shift() : 첫 요소 추출

  • unshift(...items) : 맨 앞에 요소 추가

  • splice(pox, deleteCount, ...items) : pos부터 deleteCount개의 요소를 지우고, items 추가

  • slice(start, end) : start부터 end바로 앞까지 요소를 복사해 새로운 배열 만듬

  • concat(...items) : 배열 모든 요소를 복사, items를 추가해 새로운 배열을 만든 후 이를 반환.

    • items가 배열이면 이 배열의 인수를 기존 배열에 더해준다.

원하는 요소 찾기

  • indexOf/lastIndexOf(item,pos) : pos부터 원하는 item을 찾는다. 찾게 되면 해당 요소의 인덱스를, 아니면 -1을 반환

  • includes(value) : 배열에 value가 있으면 true를, 그렇지 않으면 false를 반환

  • find/filter(func) : func의 반환 값을 true로 만드는 첫 번재/전체 요소를 반환

  • findIndex : find와 유사. 다만 요소 대신 인덱스를 반환

배열 전체 순회하기

  • forEach(func) : 모든 요소에 func을 호출 > 결과는 반환되지 않음

배열 변형하기

  • map(func) : 모든 요소에 func를 호출 > 반환된 결과를 가지고 새로운 배열을 만듬

  • sort(func) : 배열을 정렬 > 정렬된 배열을 반환

  • reverse() : 배열을 뒤집어 반환

  • split/join : 문자열을 배열로, 배열을 문자열로 변환

  • reduce(func, initial) : 요소를 차례대로 func을 호출 > 반환값은 다음 함수 호출에 전달 > 최종적으로 하나의 값이 도출

기타

  • Array.isArray(arr) : arr이 배열인지 여부를 판단(true, false)

    sort, reverse, splice는 기존 배열을 변형시키는 점에서 주의하기

이외의 배열 메서드

  • arr.some(fn)arr.every(fn)는 배열을 확인한다.

    • 두 메서드는 map과 유사하게 모든 요소를 대상으로 함수 호출을 한다.

    • some은 함수 반환값을 true로 만드는 요소가 하나라도 있는지 확인하고

    • every모든 요소가 함수 반환값을 true로 만드는지 여부를 확인한다.

    • 두 메서드 모두 조건을 충족하면 true, 그렇지 않으면 false를 반환.

  • arr.fill(value,start,end)는 start부터 end까지 value를 채워 넣는다.

  • arr.copyWithin(target,start,end)는 start부터 end까지 요소를 복사 > 복사한 요소를 target에 붙여넣는다. (기존 요소가 있다면 덮어 씌운다)

profile
90% of my problems magically disappeared when I slept well, ate well and went on regular walks

0개의 댓글