기억의 실마리
2023. 2. 4. 18:00

Array - 배열

  • 정의
    배열은 index를 가지며 여러 자료를 저장할 수 있는 자료구조이다.
    중복도 가능하며 저장된 데이터는 인덱스를 통해 접근이 가능하다.

  • 속성
    객체와 같이 여러자료를 저장할 수 있는 자료구조
    이다.
    index / value 를 Pair로 저장되는 구조이다.
    index는 배열의 length -1 이며 0부터 시작한다. ( [1,2,3] => index : 0,1,2 )

 

배열 만들기

  • 배열도 객체와 마찬가지로 빈 배열을 변수에 할당해주어 사용한다.
let arr = [];

 

  • 예시 데이터
let arr = [1,"two",3,{name:"bob smith"},[1,2,3]];

 

배열의 인덱스값(index value)에 접근하기

// arr = [1,"two",3,{name:"bob smith"},[1,2,3]];

console.log(arr[0]);  // 1
console.log(arr[1]);  // two
console.log(arr[3]);  // {name: 'bob smith'}
console.log(arr[4]);  // [1, 2, 3]

//배열 내부의 오브젝트 키값에 접근하기
console.log(arr[3].name); // bob smith

//배열 내부의 배열 인덱스값에 접근하기
console.log(arr[4][0]);  // 1
console.log(arr[4][1]);  // 2

배열 내부 오브젝트(객체)에 접근하는 방식은 프로퍼티 접근연산자   .   (dot notation)를 사용하면 된다.

배열 내부에 배열로 접근하기 위해선  arr[4][0]  대괄호(bracket)를 연속으로 사용하여 접근 할 수 있다.

 

 

 

배열에 새로운 요소 추가

  • push()와 arr.length를 이용한 추가방식
// arr = [1,"two",3,{name:"bob smith"},[1,2,3]];

//push()를 이용한 추가방식
console.log(arr.push(1995));  // 6
console.log(arr);
// [1,"two",3,{name:"bob smith"},[1,2,3],1995]


//length를 이용한 추가방식
arr[arr.length] = "last"
console.log(arr);
// [1,"two",3,{name:"bob smith"},[1,2,3],1995,"last"]

push()는 추가된 이 후의 길이인 arr.length를 반환한다.

 

 

  • unshift()로 첫번째 위치에 요소 추가하기
let newArr = [2,3];

console.log(newArr.unshift(1));  // 3

console.log(newArr);  // [1, 2, 3]

unshift()는 추가된 이 후의 길이인 arr.length를 반환한다.

 

 

배열 요소 삭제

  • delete로 삭제하기
// arr = [1,"two",3,{name:"bob smith"},[1,2,3],1995,"last"]

delete arr[6];

console.log(arr);
// [1,"two",3,{name:"bob smith"},[1,2,3],1995, 비어있음 ]

console.log(arr[6]);
// undefined

console.log(arr.length);
// 7

delete로 삭제를 하게되면 해당 요소전체가 삭제되는 것이 아니라 해당 값만 undefined가 된다.

따라서 보는 것 과 같이 index는 남아있기 때문에 배열의 길이는 그대로이다.

무작정 delete를 사용해서 배열을 삭제하기보다 용도에 따라 사용하는 것이 적합할 것 같다.

 

 

  • pop()으로 삭제
// arr = [1,"two",3,{name:"bob smith"},[1,2,3],1995, 비어있음 ]

console.log(arr.pop());
// undefined

console.log(arr);
// [1,"two",3,{name:"bob smith"},[1,2,3],1995]

pop()은 접근한 배열의 마지막 요소를 삭제하고 삭제된 요소의 값을 반환한다.

delete와는 다르게 index/value를 pair로 삭제하기 때문에 length도 줄어들게된다.

 

 

  • splice()로 선택삭제, 교체

    ex) splice(삭제시작index: 0, 지울갯수(옵션): 1, 교체할요소(옵션): "Hello");
         첫번쨰 인자만 넣어 줄 경우 입력한 시작인덱스 뒤로 모두 삭제한다.
         첫번째 인덱스에서 한개 = 첫번째 인덱스이다.  삭제 후 "Hello"요소를 넣어준다.
// arr = [1,"two",3,{name:"bob smith"},[1,2,3],1995]

console.log( arr.splice(0,1) );  // [1]
console.log(arr);  // ["two",3,{name:"bob smith"},[1,2,3],1995]


console.log( arr.splice(2,1,{name: "bori-bob black-smith"}) );
// {name: "bob smith"}
console.log(arr);
// ["two",3,{name:"bori-bob black-smith"},[1,2,3],1995]

splice()는 pop()과 마찬가지로 삭제한 요소를 반환한다.

splice()는 삭제뿐 아니라 새로운 요소를 넣어 줄 수도 있기 때문에 잘 기억해두면 좋을 것 같다.

 

 

배열 연결하기

const arr1 = ["one", "two", "three"];
const arr2 = [4, 5, 6];
const arr3 = ["칠", "팔", "구", "십"];

const linkedArr = arr1.concat(arr2, arr3);
console.log(linkedArr);
// ['one', 'two', 'three', 4, 5, 6, '칠', '팔', '구', '십']

const linkedArr2 = arr3.concat(arr2,arr1);
console.log(linkedArr2);
// ['칠', '팔', '구', '십', 4, 5, 6, 'one', 'two', 'three']

 

 

  • concat()을 사용하여 배열 복제하기
const arr1 = ["a", "b", "c", "d", "e", "f"];

const arr2 = [].concat(arr1);

console.log(arr1)  // ["a", "b", "c", "d", "e", "f"]
console.log(arr2)  // ["a", "b", "c", "d", "e", "f"]

빈배열에 .concat(복제할배열) 을 하게되면 해당 변수에 복사되어 할당된다.

 

 

 

특정 조건을 만족하는 요소만 필터링하기

  • filter()로 필터링하기

    ex) filter(function(배열의요소: value, 인덱스(옵션): index, 함수를호출한배열(옵션): array));
const mergeArr = ["one", "two", "three", 1, 2, 3];

const filterArr = mergeArr.filter(value => typeof value === "number");

console.log(filterArr);  // [1, 2, 3]



/* 모든 옵션을 사용해서 적용 */
const mergeArr2 = ["one", "two", "three", 1, 2, 3];

const filterArr2 = mergeArr2.filter( (value, index, array) => {
console.log(`${index} index의 값: ` + value);
/* console.log
0 index의 값: one
1 index의 값: two
2 index의 값: three
...
*/

return (typeof value === "string") && (typeof array[index] === "string");
} );

console.log(filterArr2);  // ['one', 'two', 'three']

filter()를 사용하면 console.log()를 통해서배열 모두를 순회하는 것을 확인할 수 있다.

그리고 filter함수는 내부 함수를 조건으로서 반환되는 값을 true / false 여부에 따라서 추가할지 버릴지 판단하게 된다.

필터링 된 배열을 저장할 변수가 필요하니 반드시 변수에 할당시켜주자.

 

 

 

배열내의 요소를 가공하기

  • map()을 사용하여 요소를 변경한 새로운 배열을 만들기

    ex) map(function(배열의요소: value, 인덱스(옵션): index, 함수를호출한배열(옵션): array));
const numArr = [1, 3, 15, 22];
const mapArr = numArr.map((value,index) => {
    console.log(`${index+1}번째: ` + value);
    /* console.log
    1번째: 1
    2번째: 3
    3번째: 15
    4번째: 22
    */
    return `${index+1}번째: ` + value * 100
})
console.log(mapArr);
// ['1번째: 100', '2번째: 300', '3번째: 1500', '4번째: 2200']

map()을 사용하면 filter()와 마찬가지로 배열 모두를 순회하는 것을 확인할 수 있다.

return하는 값을 순회하면서 모두 적용시켜 주는 배열을 반환한다.

 

 

 

요소를 순회하며 연산하기

  •  reduce()를 사용하여 요소의 값을 순회하며 연산

  • ex ①  reduce (샐행값을 누적하는 콜백함수: callback, 초기값: initiaValue);

  • ex ②  callback (
                    callback함수의 반환값을 누적: accumulator,
                                         
    배열의 현재요소: currentValue,
                                      배열의 현재인덱스: index,
                                                호출한 배열:
    array
    ) { ... return accumulator  }

 

 

reduce의 작동방식

1. 각 요소의 전체를 순회연산할때의 initialValue

  • 초기값을 설정하면 연산을 시작할때 초기값으로 설정된다. 
    또한 순회하는 각 요소의 전체가 대입되어 연산해야 하는 경우에 초기값을 생략가능하다.
    ex) [1,2,3,4,5] 요소를 순회하며 더할 경우

 

2.  요소가 배열, 객체이며 특정 index || key의 값으로 순회연산할때의 initialValue

  • 초기값은 똑같이 초기값으로 적용되나, 특정 index나 key값으로 순회연산할때는
    initialValue 설정하지 않으면 원치않는 결과를 마주하게 될 수도 있다.

  • reduce()함수는 최초 호출 시
    callback => initialValue => crrentValue => currentIndex 순으로 동작하는데

    initialValue의 자리가 비어 있는 경우그 자리를 crrentValue가 대체 해버린다.

    callback => crrentValue => crrentValue => currentIndex 순서가 이렇게 변동 되어서
    crrentValue순서가 + 1이 되어버린다.

    그러므로 순서대로 작동하게 만드려면 반드시 initialValue에 0을 설정해두자

  • initialValue를 설정하지 않는경우 강제적으로 currentIndex가 1이되어
    가장 첫번째 요소인 index 0 은 건너뛰게 되는데 이 경우 callback호출없이
    요소 자체를 반환하게 되고 이후 연산은 강제로 문자열연산으로 변환된다.
    ex) 
            [ { name: "a", age: 30 }, { name: "a", age: 20 }, { name: "a", age: 30 }, { name: "a", age: 20 }, ]
            / /  Object.age를 모두 더하는 reduce()

            O  =>   100
            X   =>   [object Object]203020

 

3. initialValue에 의한 순서 변화

  • callback =>   initialValue =>   crrentValue =>   currentIndex
        콜백               초기값               첫번째요소               0

  • callback =>   crrentValue =>   crrentValue =>   currentIndex 
        콜백              첫번째요소        두번째요소                1

 

reduce 예시

  • 요소 모두 더하기
const numArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const sumAll = (accumulator, currentNum) => {
  return accumulator + currentNum;
}

const result = numArr.reduce(sumAll); 
// reduce내부에서 직접적으로 함수를 넣어줘도 무관하다.
// 요소자체를 순회연산 하고 특정 key값이나 객체가 아니므로 initialValue 생략가능.

console.log('result =', result); // result = 55

 

  • 객체 요소에서 특정 key의 값만 모두 더하기
const objArr = [
	{
		name: 'Danaka',
		age: 39,
	},
	{
		name: 'B',
		age: 40,
	},
	{
		name: '민식이',
		age: 30,
	},
	{
		name: '준식이',
		age: 30,
	},
];

const result = objArr.reduce((accumulator, currentObj) => {
  return accumulator + currentObj.age;
}, 0);

console.log('result =', result); // result = 139

 

 

 

배열정렬하기

  • sort()를 사용하여 정렬

  • sort(정렬순서를 정의하는 함수:compareFunction);
    compareFunction는 두개의 배열 요소를 매개변수로 입력받는다.

  • 매개변수 a, b에 의한 정렬기준
    생략  =  요소가 문자열로 취급되며 유니코드 값의 순서로 정렬된다.
    반환되는 값이 음수  =  a가 b보다 앞에 오도록 정렬한다.
    반환되는 값이 양수  =  b가 a보다 앞에 오도록 정렬한다.
    반환되는 값이 0이면  =  순서를 변경하지 않는다.

 

1.문자열 정렬

const abcArr = ['B', 'C', 'A', 'E', 'D'];
const abcArr2 = abcArr;
const abcArr3 = abcArr;
const abcArr4 = abcArr;

//오름차순 (Default)
abcArr.sort();
console.log(abcArr); // ['A', 'B', 'C', 'D', 'E']


//문자열 내림차순은 조건문을 잘 달아줘야 한다.
abcArr2.sort(function (a, b) {
    if (a > b) return -1;
    if (b > a) return 1;
    return 0;
});
console.log(abcArr2); // ['E', 'D', 'C', 'B', 'A']


//두번째 방법으론 reverse()함수를 사용하는 것이다. 로직상 비효율적이지만 코드는 짧아진다.
abcArr3.sort();
abcArr3.reverse();
console.log(abcArr3); // ['E', 'D', 'C', 'B', 'A']




//가장 간결하고 효율적인 삼항연산자 (가독성은 좋지 않다)
abcArr4.sort((a, b) => a>b ? -1 : b>a ? 1 : 0);
console.log(abcArr4); // ['E', 'D', 'C', 'B', 'A']

 

 

 

2.숫자 정렬

// 숫자의 경우 반드시 비교조건문을 넣어줘야한다.
const numArr = [200, 101, 2, 9, 1, 5];
const numArr2 = numArr;
const numArr3 = numArr;

// 조건문을 넣지 않았을때
numArr.sort();
console.log(numArr);  // [1, 101, 2, 200, 5, 9]


// 오름차순
numArr2.sort((a, b) => a - b);
console.log(numArr2);  // [1, 2, 5, 9, 101, 200]


// 내림차순
numArr3.sort((a, b) => b - a);
console.log(numArr3);  // [200, 101, 9, 5, 2, 1]

 

배열 초기화하기

  • 직접 값을 할당하여 초기화하기

  • new 생성자함수를 사용하여 초기화 하기
// 직접 값을 할당시켜주어 초기화 시킨다.
let arr = [1, 2, 3, 4, 5];

// new 생성자 함수를 사용하여 배열을 형성하고 fill함수를 사용하여 모든 요소에 값을 넣어준다.
let arr = new Array(5).fill(0);

/*
   길이가 5이면서 모든 원소의 값이 0인 배열로 초기화된다.
   arr = [0, 0, 0, 0, 0]
*/

 

 

마치며...

생각했던 것 보다 포스팅하는 시간이 길었던 것 같다. 전반적으로 객체보다도 더 데이터 가공성이 뛰어난게 배열인 것 같다고 생각을 했다. 물론 상황에 따라 다르겠지만... :) 그리고 개발을 하면서 데이터를 가공할 일이 점점 많아지기 때문에 배열과 객체를 많이 다루게 되는 것 같다.