AngeRay 2021. 9. 15. 19:04

Array


자료구조 중 하나인 array

자료구조란? 

프로그래밍 언어에서도 비슷한 종류의 데이터들을 묶어서 한 데다가 보관해 놓고 이런것들을 자료구조 라고 한다.

자료구조에는 어떤 방식으로 어떤 형식으로 데이터를 담느냐에 따라서 굉장히 다양한 타입들이 있다.

 

자료구조와 object의 차이점

비슷한 종류의 데이터를 묶어놓은 것은 오브젝트라고 했다.

그렇다면 오브젝트와 자료구조의 차이점은 무엇일까?

 

 

오브젝트는 토끼와 당근이 될 수 있다.

토끼는 동물이고 귀가 2개인 properties가 들어 있을 수 있고

먹는다, 뛴다 라는 함수들 메소드가 들어 있을 수 있다.

당근은 주황색이고 비타민A가 있는 properties가 있을 수 있지만,

당근 자체로는 어떤 행동을 할 수 없기때문에 메소드가 없을 수 있다.

이렇게 오브젝트는 서로 연관된 특징과 또는 행동들을 묶어놓는 것을 말한다.

토끼, 사람, 자동차 이런 것들처럼 말이다.

여기에서 이런 토끼, 당근을 비슷한 타입의 오브젝트들을 묶어놓는 것을 자료구조 라고 한다.

 

보통 다른 언어에서는 이런 자료구조에는 동일한 타입의 오브젝트를 담을 수 있다.

이렇게 타입이 있는 언어에서는 동일한 타입의 데이터만 담을 수 있다.

하지만 자바스크립트는 dynamically typed language 즉 동적으로 정의된다.

 

 

그래서 이런 미친짓이 가능하다.

즉 한 바구니 안에 다양한 종류의 데이터를 담을 수 있다.

하지만 이런 식으로 프로그래밍을 하는 것은 좋지않다.

 

 

배열은 이렇게 칸칸이 모여있는 자료구조를 말한다.

그리고 여기서 중요한 점은 인덱스가 지정되어져 있다는 것이다.

그리고 인덱스는 0부터 시작한다.

위 이미지에서 배열의 사이즈는 5이다.

즉 이 박스들은 모여있고 박스에 인덱스 번호가 매겨져 있다.

 

그리고 프로그래밍 언어에서 인덱스는 0부터 시작한다.

여기에 우리가 준비한 토끼와 당근들을 담아 놓으면 위 이미지 처럼 보여진다.

위 이미지처럼 배열을 이용해서 자료들을 보관할 수 있다.

그리고 보통은 한 배열 안에는 동일한 타입의 데이터를 넣는 것이 중요하다.

 

자바스크립트에서는 여러가지의 타입의 데이터를 한 배열안에 넣을 수 있지만 되도록이면 이렇게 하지 않는것이 좋다.배열의 포인트는 인덱스 이다.만약 데이터를 삽입, 삭제 하고 싶다면 인덱스로 접근하기 때문에 너무 쉽다.

 

Array Declaration

배열을 선언하는 방법은 2가지가 있다.

const arr1 = new Array();

이렇게 new라는 키워드를 이용해서 우리가 오브젝트를 만드는 것처럼 배열을 만들 수 있다.

 

const arr2 = [1, 2];

더 흔하게 쓰이는 방법인데 이렇게 []를 이용하여 데이터를 넣어서 배열을 만들 수 있다.

지금 총 길이가 2개인 배열이 만들어 졌고, 0번째 인덱스에는 숫자1, 1번째 인덱스에는 숫자2가 들어있는 배열이 만들어 졌다.

 

Index position

배열을 공부할 때는 배열이 인덱스를 기준으로 데이터가 저장되기 때문에

인덱스를 활용해서 어떻게 데이터는 검색하고, 삽입, 삭제 하는지 이런 것들을 정확하게 아는 것이 중요하다.

인덱스를 통해 어떻게 배열을 접근 가능한지 알아보자

 

 

fruits의 length는 2개이다.여기서 첫번째 사과에 접근하려면 어떻게 해야할까?바로 배열에서는 []로 데이터에 접근 가능하다.우리가 오브젝트에서 많이 봤던 모양이다.오브젝트 에서는 key라는 string을 이용하게 되면 즉 string안에 key 라는 즉 예를들어 name, age 이런것들을 쓰게되면 그에 상응하는 value값을 받아 올 수 있다.

 

 

만약 그 밖에 있는 인덱스를 접근하게 되면 undefined 

즉 아무것도 들어있지 않기 때문에 undefined가 나온다.

그래서 보통 배열의 첫번째 아이템을 찾을 때는 0, 

배열의 제일 마지막에 있는 아이템을 찾을 때는 배열의 길이에 -1을 해서 마지막 데이터를 접근할 수 있다.

배열은 인덱스가 0부터 시작하기 때문에 총 길이에 -1을 하면 제일 마지막 인덱스를 받아 올 수 있다.

 

for each

콜백함수를 받아온다.

어떤 것을 수행하는 함수인데 정해진 액션을 수행하는 함수 이다.

각각 element에 즉 array안에 들어 있는 element 이 말은 array에 들어있는 값마다 우리가 전달한 액션 즉 콜백함수를 수행한다.

총2가지의 파라미터가 전달된다.

첫번째는 콜백함수 우리가 전달한 이 함수를 value 하나하나마다 호출해주는 것이다.

두번째로 ? 표시가 되어있으면 파라미터를 전달해도 되고 전달하지 않아도 되는것이다.

우리가 전달한 콜백함수를 value마다 호출해주고 

이 콜백함수에는 총 3가지의 인자가 들어온다.

첫번째 value 즉 우리가 콜백함수를 호출하는 그 value 배열에 있는 값이 전달되고

그 값이 들어있는 인덱스도 들어오고 전체적인 배열도 이렇게 전달을 받을 수 있다.

for each는 함수가 전달 가능하다.

for each는 배열 안에 들어 있는 value마다 내가 전달한 함수를 출력한다.

 

** 이름이 없는 function은 arrow function이 사용 가능하다.

 

 /**
     * Performs the specified action for each element in an array.
        배열의 각 요소에 대해 지정된 작업을 수행합니다.
     * @param callbackfn  A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
        param callbackfn 최대 3개의 인수를 허용하는 함수입니다. forEach는 배열의 각 요소에 대해 callbackfn 함수를 한 번 호출합니다.
     * @param thisArg  An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
     */
    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: ny): void;a
 

if 배열에 어떻게 데이터를 넣고, 빼고 그리고 복사 할 수 있을까?

 아이템을 어떤 value들을 배열의 제일 뒤에다 놓을것인지?

그리고 배열에서 제일 뒤에서 부터 아이템을 지우고 싶은지?

제일 뒤에 넣는것은 push, 넣는 것은 pop

 

    /**
     * Appends new elements to the end of an array, and returns the new length of the array.
     * @param items New elements to add to the array.
     */
    push(...items: T[]): number;
 
    /**
     * Removes the last element from an array and returns it.
     * If the array is empty, undefined is returned and the array is not modified.
     */
    pop(): T | undefined;
 
그렇다면 앞에서부터 아이템을 넣고 빼는것도 가능한가?
앞에서 부터 넣는 unshift, 앞에서 부터 빼는 shift
 
 /**
     * Inserts new elements at the start of an array, and returns the new length of the array.
     * @param items Elements to insert at the start of the array.
     */
    unshift(...items: T[]): number;
 
/**
     * Removes the first element from an array and returns it.
     * If the array is empty, undefined is returned and the array is not modified.
     */
    shift(): T | undefined;
 
 
** unshift, shift는 push, pop 보다 많이많이 느리다.

 

이유는 배열의 아이템들이 들어 있을 때 뒤에서 부터 넣고, 빼고는

빈공간에 데이터를 넣고, 빼고를 하기 때문에 기존에 들어 있던 데이터들은 움직이지 않아도 되어서

한 공간에 인덱스를 이용해서 넣고, 빼고가 되기 때문에 정말 빠른 오퍼레이션이 진행 가능하다.

우리가 반대로 앞에서 데이터를 넣게 되면 여기에 있던 데이터를 옮겨서 넣고 

텅텅 비게 만든 다음에 새로운 데이터를 집어 넣어야 한다.

 

반대로 데이터 삭제시 첫번째 아이템을 지우고 당겨오고 또 그 다음걸 당겨오고 

이런식으로 계속 반복해 줘야 되는 것이다.

그래서 배열의 길이가 길수록 shift하다, 당겨오다, 움직이다 이런 일들을 계속해서 반복적으로 해야되기에 

가능하면 pop과 push를 사용한다.

 

또한 제일 뒤에서 아이템을 접근하는 것은 빠르고 중간에 데이터를 넣고, 빼는 것도 인덱스를 활용해서 하기 때문에 빠르다.

shift, unshift는 배열의 길이가 길면 길수록 전체적으로 움직여야 되는 것들이 많기때문에 더 느리다.

 

if 지정된 포지션에서 아이템을 지우고는 것은 가능할까?

splice를 사용한다.

이 API를 사용하면 우리가 지정된 위치에서 데이터를 삭제할 수 있다.

어디서 부터 지울건지 즉 시작하는 인덱스의 번호를 지정해주고 

몇개나 지울 건지 말해주면 된다.

deleteCount 옆에 ?는 옵션을 즉 값을 지정해도 되고 안해도된다는 의미 이다.

 

또한 splice를 한다음에 원하는 데이터가 추가 가능하다.

아이템을 지우지 않고 원하는 데이터 추가도 가능하다.

 

/**
     * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
     * @param start The zero-based location in the array from which to start removing elements.
     * @param deleteCount The number of elements to remove.
     * @param items Elements to insert into the array in place of the deleted elements.
     * @returns An array containing the elements that were deleted.
     */
    splice(start: number, deleteCount: number, ...items: T[]): T[];

 

 

두 가지의 데이터를 묶어서도 만들 수 있다.

/**
     * Combines two or more arrays.
     * This method returns a new array without modifying any existing arrays.
     * @param items Additional arrays and/or items to add to the end of the array.
     */
    concat(...items: ConcatArray<T>[]): T[];
 

indexOf, includes, lastIndexOf

배열 안에 내가 원하는 아이템이 몇 번째 인덱스에 있는지 알고싶다면 indexOf

 - 제일 첫번째로 해당하는 값을 만나면 그 값이 들어있는 인덱스를 리턴하게 된다. 

 - 제일 마지막 중복되는 아이템의 index를 출력하는 lastIndexOf

 

배열에 내가 원하는 아이템이 있는지 없는지 true or false 로 리턴하는 함수인 includes