민희의 코딩일지

[JS] Learning JavaScript Data Structures and Algorithms 2장.배열 본문

자료구조, 알고리즘/자바스크립트

[JS] Learning JavaScript Data Structures and Algorithms 2장.배열

heehminh 2023. 1. 7. 21:28
반응형

배열은 동일한 데이터 타입의 값들을 연속적으로 저장한 것이다. 자바스크립트에서는 상이한 타입의 데이터도 한 배열에 넣을 수 있다. 

1. 배열의 생성과  초기화

자바스크립트에서 배열을 선언하는 방식은 두가지가 있다. 

1) new 를 사용하여 배열 선언

let daysOfWeek = new Array();
let daysOfWeek2 = new Array(7);
let daysOfWeek3 = new Array("일","월","화","수","목","금","토");

2) []을 사용하여 배열 선언 (권장)

let daysOfWeek4 = [];

* 피보나치 수열의 처음 20개 숫자 구하기 (피보나치 수열은 1과 2로 시작하고 이후의 숫자는 앞의 두 숫자의 합이다)

// 피보나치 수열의 처음 20개 숫자를 구하는 코드 
let fibonacci = [];

// 자바스크립트의 배열의 인덱스는 항상 0부터 시작하지만, 0번째 피보나치 수열이란 없으니 건너뛴다
fibonacci[1] = 1;
fibonacci[2] = 2;

for (let i=3; i<20; i++) {
    fibonacci[i] = fibonacci[i-2] + fibonacci[i-1];
}

let result = "";

for (let i=1; i<fibonacci.length; i++) {
    result += " "+fibonacci[i];
}
console.log(result);

 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

(result를 사용한 이유: console.log() 는 시간, 메모리 낭비가 심하다)


2. 원소 추가와 삭제

추가

자바스크립트 배열은 mutable 객체이다. 원소를 쉽게 추가할 수 있고 객체는 동적으로 커진다. 

배열의 맨 마지막에 새 원소를 추가하는 방식은 두 가지가 있다.

1) 가장 마지막 인덱스에 원하는 값을 할당

let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers[numbers.length] = 10;

 

2) push 메소드 이용

numbers.push(11);
numbers.push(12, 13);
console.log(numbers);

[
   0,  1, 2, 3,  4,  5,
   6,  7, 8, 9, 10, 11,
  12, 13
]

 

배열의 앞부분에 새 원소를 추가하는 방식 

1) 먼저 기존에 들어 있던 원소를 전부 우측으로 한 칸씩 이동시켜 첫 번째 위치를 비워놓고, 마지막에 새로운 값을 첫번째 위치에 할당하는 방식

for (let i=numbers.length; i>=0; i--) {
    numbers[i] = numbers[i-1];
}
numbers[0] = -1;

 

2) 자바스크립트 내장 함수 Arrays.unshift 를 사용하여 배열 앞부분에 삽입할 값을 인자로 넘겨주는 방식 

numbers.unshift(-2);
numbers.unshift(-4, -3); // -4, -3 순으로 들어감

 

삭제

배열 뒷부분의 값을 삭제할 때 쓰는 메소드

numbers.pop(); // 13이 삭제됨

pop을 사용하면 배열의 length가 1개 줄어든다.

 

배열 앞부분의 값을 삭제하는 방식 

1) 덮어쓰는 방식

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

모든 원소를 한 칸씩 좌측으로 옮겼는데도 배열의 크기는 여전히 17이다. 즉 배열에 잉여 원소 (값: undefined)가 발생했다는 의미이다.

 

 

 

2) 내장 메소드 shift를 사용하여 완전히 삭제하는 방식 (* shift, unshift는 배열로 기본 큐 자료 구조를 모방한 메소드이다)

numbers.shift();

배열의 length가 1개 줄어든다.

 

배열의 특정 위치에 원소를 추가/삭제할 때 : splice 메소드 사용 

numbers.splice(5, 3);

인덱스 5에서 시작되는 3개의 원소를 날린다 (5, 6, 7 삭제)

numbers.splice(5, 0, 2, 3, 4);

- 첫번째 인자: 원소를 추가/삭제하려는 인덱스
- 두번째 인자: 삭제할 원소의 개수 (개수가 0이면 삭제하지 않겠다)
- 세번째 인자 이후로는 배열에 추가할 원소들을 나열한다. 


3. 2차원과 다차원 배열

let averageTempDay = []
averageTempDay[0] = [72, 75, 79, 79, 81, 81];
averageTempDay[1] = [81, 79, 75, 75, 73, 72];

function printMatrix (myMatrix) {
    for (let i=0; i<myMatrix.length; i++) {
        myMatrixResult = "";
        for (let j=0; j<myMatrix[i].length; j++) {
            myMatrixResult += " " + myMatrix[i][j];
        }
        console.log(myMatrixResult)
    }
}

printMatrix(averageTempDay);

4. 자바스크립트 배열 메소드 정리 

push 배열의 맨 마지막에 새 원소를 추가
pop 배열 뒷부분의 값을 삭제
shift 배열 앞부분의 값을 삭제
unshift 배열의 앞부분에 새 원소를 추가
splice 배열의 특정 위치에 원소를 추가/삭제
concat 다수의 배열을 합치고, 병합된 배열의 사본을 반환한다
every false가 반환되기 전가지 배열의 각 원소별로 함수를 호출한다
filter 지정된 함수의 결과 값을 true로 만드는 원소들로만 구성된 별도의 배열을 반환한다
forEach 배열의 각 원소별로 지정된 함수를 실행한다
join 배열 원소 전부를 하나의 문자열로 합친다
indexOf 특정 원소의 인덱스를 찾아 반환한다
lastIndexOf 검색 조건에 부합하는, 가장 마지막에 위치한 원소를 찾아 그 인덱스를 반환한다
map 배열의 각 원소별로 지정된 함수를 실행한 결과로 구성된 새로운 배열을 반환한다
reverse 배열의 원소 순서를 거꾸로 바꾼다
slice 지정된 인덱스부터 원소를 잘라 새로운 배열을 반환한다
some 지정된 함수의 결과 값을 ture로 만드는 원소 각각을 전달한다
sort 배열의 원소를 알파벳순으로, 또는 지정된 함수에 따른 순서로 결정한다
toString 배열을 문자열로 바꾸어 반환한다
valueOf toString 메소드와 같다. 배열을 문자열로 반환한다

 

1. 여러 배열 합치기

// 여러 배열 합치기 (concat)
let zero = 0;
let positiveNumber = [1, 2, 3];
let negativeNumber = [-3, -2, -1];
let numbers = negativeNumber.concat(zero, positiveNumber);

 

2. 반복자 함수

const isEven = (x) => {
    // x가 2의 배수이면 true 반환
    return (x%2)==0 ? true : false;
}

numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// 1. every: false가 반환될 때까지 호출 (1, 2) 
numbers.every(isEven);

// 2. some: true가 반환될 때까지 호출 (1)
numbers.some(isEven);

// 3. forEach 메소드: 배열의 각 원소별로 지정된 함수를 실행한다
numbers.forEach(element => 
    console.log(element%2==0);
})

numbers.forEach(function(element) {
	console.log(element%2==0);
 });

every 메소드는 조건을 만족하지 않는 값이 발견되면 그 즉시 순회를 중단한다. some 메소드는 조건을 만족하는 값이 발견되면 그 즉시 순회를 중단한다. forEach 메소드는 배열의 각 원소별로 지정된 함수를 실행한다. numbers 안의 각 원소를 element에 할당해주고 element%2==0 을 실행시킨다. 

 

아래 메소드 3개는 수행 결과를 새 배열 객체로 반환하는 메소드이다. 

// 4. map: 배열의 각 원소별로 지정된 함수를 실행한 결과로 구성된 새로운 배열 반환
// 원래 배열의 length와 새로운 배열의 length 같음
let myMap = numbers.map(isEven);
// 결과: false true false true ... 

// 5. filter: 함수의 결과값을 true로 만드는 원소로만 구성
let evenNumbers = numbers.filter(isEven);
// 결과: 2 4 6 8 ...

// 6. reduce: 인자로 previousValue, currentValue, index, array 를 인자로 받는 함수 지정
// 모든 배열 원소 값의 총합을 구할 때 유용함
const result = numbers.reduce((previous, current, index) => {
    return previous += current;
}, 0);
console.log(result); // 120

위 예제에서 initialValue 값을 0으로 두었기 때문에 previous 의 초기값은 0이 되고 배열의 첫번째요소부터 previous에 자신의 값인 current를 더해준다. 

 

// initialValue에 배열이 들어가는 경우: 주어지는 배열에서 음수와 양수의 개수를 카운트해서 출력하는 경우
// previous[0]: 음수의 개수, previous[1]: 양수의 개수
const example = [2, -5, -123, 59, -5480, 24, 0, -69, 349, 3];
const example_result = example.reduce( (previous, current, index) => {
    if (current < 0) {
        previous[0]++;
    } else if (current > 0) {
        previous[1]++;
    }
    return previous;
}, [0, 0]);
console.log(example_result);

 

3. 검색과 정렬 

배열에서 원소 순서를 거구로 바꾸고 싶을 경우

numbers.reverse();

 

sort 메소드

arr.sort([compareFunction]) 

파라미터 compareFunction은 정렬 순서를 정의하는 함수이다. 이 값이 생략되면 배열의 element들은 문자열로 취급되어 유니코드 값 순서대로 정렬된다. 

 

a. 숫자형 오름차순 정렬 

// sort()를 이용하여 숫자형 배열을 오름차순 정렬하는 방식
numbers.sort(function(a,b){
	return a-b;
});

function compare(a,b) {
    if (a<b) return -1; // return value < 0 이므로 a는 b앞에 온다
    if (a>b) return 1;
    return 0;
}
numbers.sort(compare);

b가 a보다 크면 양수, a가 b보다 크면 음수, a와 b가 같으면 0을 반환하는 함수다. 이러한 결과 값을 기준으로 원소들을 정렬한다. 

 

b. 사용자 정의 정렬

let friends = [
    {name: 'John', age: 34},
    {name: 'Camila', age: 21},
    {name: 'Jack', age: 30}
];

function comparePerson(a,b) {
    if (a.age < b.age) return -1;
    if (a.age > b.age) return 1;
    return 0;
}

console.log(friends.sort(comparePerson));

 

c. 문자열 정렬 

// 대소문자 구분 (대문자 < 소문자)
let names = ["Ana", "ana", "john", "John"];
console.log(names.sort());

// 대소문자 구분 없이
console.log(names.sort(function(a,b) {
    if (a.toLowerCase() < b.toLowerCase()){
        return -1;
    }
    if (a.toLowerCase() > b.toLowerCase()) {
        return 1;
    } return 0;
}));

sort() 메소드는 문자의 아스키 값을 비교하기 대문에 대소문자가 구별된다.

대소문자 구별 없이 문자를 비교하려면 .toLowerCase()를 사용해주면 된다.

악센트를 제거하고 문자를 비교하려면 .localeCompare()를 사용해주면 된다. 

 

 

4. 배열을 문자열로 변환

// toString(): 배열의 모든 원소를 단일 문자열로 바꿀때
console.log(numbers.toString());

// join(): 구분자를 넣고 싶을 때
const numberString = numbers.join("-");
console.log(numberString);

 

 

반응형
Comments