본문 바로가기
javascript

[자바스크립트 자료구조] 배열

by jinbro 2017. 5. 22.
[배열이란]
- 보통 배열을 사용하는 용도는 묶음 단위로 데이터를 구분할 때 사용함
- 기본적인 자료구조


[자바스크립트 배열]
- 자바스크립트 배열은 객체 : 내장 객체(미리 만들어져있고, 사용하면 되는 객체)
- 객체지만 내부적으로 배열로서 특화된 객체 : 배열 관련 프로퍼티
- 자바스크립트 배열은 한 배열 내 다양한 타입의 요소를 포함시킬 수 있음 : 스크립트 언어가 대부분 그럼
- 배열은 레퍼런스 타입


[자바스크립트 배열 생성 방법]
1) [ ]를 이용한 배열 선언
1
2
3
4
5
6
var numbers = [];
 
/* for문을 통해 numbers 배열에 요소 추가 */
for(var i = 0; i < 10; i++){
     numbers[i] = i+1;
}
cs


2) Array 생성자 호출1 - 배열 요소 전달
1
2
3
4
5
var numbers = new Array(); // [ ]
/* or */
 
var numbers = new Array(1,2,3,4,5); // === [1,2,3,4,5]
 
cs


3) Array 생성자 호출2 - 배열 길이 전달
1
2
var numbers = new Array(10);
console.log(numbers.length); // 10 
cs
- 인수 갯수에 따라 요소를 전달할 것(0개 or 2개 이상)인지 길이를 전달할 것(1개)인지 정해짐


[자바스크립트 배열 프로퍼티]
- 다시 말하지만 자바스크립트 배열은 (특화된)객체 : 배열 관련 메서드를 상속받고(프로토타입체인), length 내장 프로퍼티가 있음
1
console.log(numbers.length);
cs

- 아래 이미지는 배열의 __proto__ 프로퍼티 내부를 본 것 : Array prototype



[자바스크립트 배열 및 Array 메서드 활용하기]
- 아래 기능 중 브라우저의 자바스크립트 엔진에 따라 지원하지 않을 수 있음
- 지원하지않는다면 지원하는 브라우저로 테스트한 후 지원하지않는 브라우저에서는 어떻게 구현하는지 찾아보기
(MDN, Array.prototype 객체 메서드 문서를 보면 폴리필이라는 제목 아래에 그 방법이 나와있음)

1) 문자열을 쪼개 배열 만들고 출력하기 : String.prototype.split return array
1
2
3
4
5
var sentence = "안녕 나는 박진형이라고 해";
var words = sentence.split(" ");
 
for(var i = 0; i<words.length; i++)
     console.log(words[i]);
cs


2) A배열과 쌍둥이 B배열 만들기 : 레퍼런스 타입이라 같은 메모리 주소값(배열 객체를 저장)을 저장하게함
1
2
3
4
5
6
7
var arr1 = [];
for(var i=0; i<10; i++){
     arr1[i] = i + 1;
}
 
var arr2 = arr1; 
console.log(arr1 === arr2); // true
cs
- arr1의 배열요소가 변경되면 arr2도 변경 : 하나의 메모리 주소값에 있는 배열이 변경되는 것
- 이를 얕은 복사라 함


3) A배열 요소 내용만 복사하기 : 같은 메모리 주소값을 저장하는 것이 아니라 요소만 단순히 옮기는 것
1
2
3
4
5
6
7
8
9
10
11
12
13
var arr1 = [1,2,3,4,5];
 
function copy(arr){
     var result = [];
 
     for(var i=0; i<arr.length; i++)
          result[i] = arr[i];
     
     return result;
}
 
var arr2 = copy(arr1);
console.log(arr1 === arr2); // false
cs
- 1차원 배열일 때를 가정해두고 만든 함수임
- 이를 깊은 복사라 함


4) 배열의 요소로 존재하는지 알기 : Array.prototype.indexOf
1
2
3
4
var arr = [1,2,3,4,5,1];
arr.indexOf(6); // -1
arr.indexOf(1); // 0 : 배열에서 0번째에 가장 먼저 위치
arr.lastIndexOf(1); // 5
cs
- 존재할 때 배열의 요소 인덱스 값 리턴
- 존재하는데, 여러개가 존재할 대 가장 첫번째 값의 위치(인덱스)를 리턴
- 존재하지않을 때 -1 리턴 
- lastIndexOf : indexOf와는 일부 반대개념, 존재할 때 가장 뒤의 위치를 리턴해줌


5) 배열 요소를 하나로 합쳐 문자열로 만들기 : Array.prototype.join
1
2
3
4
var arr = ["안녕하세요""저는""박진형입니다."];
var str = arr.join(); 
 
console.log(str); // "안녕하세요,저는,박진형입니다."
cs
- 문자열로 만들어주긴하나, ,(콤마)로 요소들을 구분한 상태에서 문자열로 만듬


6) C배열 = A배열 + B배열 : Array.prototype.concat
1
2
3
4
var arr1 = [1,2,3,4,5];
var arr2 = [6,7,8,9,10];
 
var arr3 = arr1.concat(arr2); // [1,2,3,4,5,6,7,8,9,10]
cs
- 두 배열의 요소를 합쳐 새로운 배열 만들기
- concat 메서드를 사용한 배열이 앞에 추가되고, 인수로 전달된 배열이 뒤에 추가됨
- concat : 내부적으로 하나의 새로운 배열을 만들고 두개의 배열 요소를 새로운 배열에 집어넣음


7) 배열 요소 삭제, 추가하기 : Array.prototype.splice
1
2
3
4
5
6
var arr = [];
for(var i=0; i<20; i++)
    arr[i] = i+1;
 
arr.splice(01030,31,32);
console.log(arr); // (13) [30, 31, 32, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
cs
- splice 메서드 : 첫번째 인수 - 변경 시작 인덱스, 두번째 - 시작 인덱스부터 삭제할 길이, 세번째 인수부터- 배열에 추가할 요소
- 배열 요소를 변경하는 용도로 사용되는 메서드


8) 직관적으로 배열 요소 추가하기 : Array.prototype.push
1
2
3
4
5
6
7
8
var arr = [];
for(var i=0; i<10; i++)
     arr[i] = i+1;
 
 
arr.push(11); // === arr[arr.length] = 11;
 
console.log(arr); // (11) [1,2,3,4,5,6,7,8,9,10,11]
cs
- 배열(객체)의 length 프로퍼티를 사용해 추가 단계를 짜지않고, 직관적인 코드로 배열 요소 추가하기
- 배열 요소 끝에 추가됨


9) 첫머리에 배열 요소 추가하기
1
2
3
4
5
6
7
8
9
var arr = [1,2,3,4,5];
var length = arr.length;
var newnum = 0;
 
for(var i=length; i>=0; i--
     arr[i] = arr[i-1];
 
arr[0= newnum;
console.log(arr); // (6) [0,1,2,3,4,5]
cs
- 끝으로 하나씩 밀어야하기때문에 끝에서부터 뒤로 밀기


10) 직관적으로 첫머리에 배열 요소 추가하기 : Array.prototype.unshift
1
2
3
4
var arr = [1,2,3,4,5];
arr.unshift(-10);
console.log(arr); // (7) [-1,0,1,2,3,4,5]
 
cs
- 내부 동작은 9번과 같겠지만 직관적으로 추가하기


11) 마지막 배열 요소 삭제하기 + 꺼내기 : Array.prototype.pop
1
2
3
var arr = [1,2,3,4,5];
arr.pop();
console.log(arr); // (4) [1,2,3,4]
cs
- pop 메서드를 사용하면 배열 요소 마지막 요소가 삭제됨
- 튀어나오다


12) 첫번째 배열 요소 삭제하기 + 꺼내기
1
2
3
4
5
6
7
8
9
10
var arr = [1,2,3,4,5];
 
for(var i=0; i<arr.length; i++)
     arr[i] = arr[i+1];
 
console.log(arr); // (5) [2,3,4,5,undefined]
 
arr.pop(arr[arr.length]);
 
console.log(arr); // (4) [2,3,4,5]
cs
- 첫번째 요소부터 뒤로 밀어야하기때문에 첫번째 요소부터 시작
- 맨 뒤에 불필요한 요소가 저장되는 것과 같음 : 지워줘야함


13) 직관적으로 첫번째 배열 요소 삭제하기 + 꺼내기 : Array.prototype.shift
1
2
3
4
var arr = [1,2,3,4,5];
arr.shift(); 
console.log(arr); // (4) [2,3,4,5]
 
cs


14) splice를 이용해 중간에 배열요소 추가, 삭제하기 : Array.prototype.splice
1
2
3
4
5
6
7
var arr = [1,2,3,4,5,6,7,8,9,10];
 
arr.splice(506,6,6,6,6); 
console.log(arr); // (15) [1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6, 7, 8, 9, 10]
 
arr.splice(65);
console.log(arr); // (10) [1,2,3,4,5,6,7,8,9,10]
cs
- splice(시작인덱스, 삭제할갯수, 추가할요소, --------) : 삭제할 갯수 자리에 0이 들어가면 요소를 추가하는 것
- 추가할 요소를 전달하지않으면 삭제


15) 배열 요소 정렬하기 : Array.prototype.sort
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var nums = [52143];
nums.sort(function(a, b){
     return a-b; 
}); // (5) [1,2,3,4,5]
 
 
var person = [
     { name"jinbro", age: 26 },
     { name"james", age: 30 },
     { name"brew", age: 81 },
     { name"grand", age: 11 }
];
 
person.sort(function(a, b){
     return a.age - b.age;
}); // (4) [Object, Object, Object, Object]
 
for(var i=0; i<person.length; i++){
    console.log(person[i]); // 나이 순으로 정렬됨
cs
- sort 함수 : 배열 요소를 문자열로 변환한 뒤 유니코드 포인트 순서로 문자열을 비교하여 정렬
- sort 함수의 인자로 정수를 비교하는 함수를 넘겨줄 때 문자열로 변환하지않고 제대로 정렬함
- 비교 함수 : a와 b 두 정수를 받아 뺄셈한 결과가 a와 b의 비교 결과, a-b 결과 양수 : a, a-b 결과 0 : 같음, a-b 결과 음수 : b
- 배열 요소를 객체로 두고, 객체의 특정 프로퍼티를 기준으로 정렬할 수 있음


16) 배열 요소 역순으로 정렬하기 : Array.prototype.reverse
1
2
3
4
5
6
7
8
var nums = [1,2,3,4,5];
nums.reverse();
console.log(nums); // (5) [5,4,3,2,1]
 
var charArr = ['b''a''z''e''f'];
charArr.sort().reverse().join(''); // "zfeba"
 
cs
- 배열 요소를 뒤죽박죽 섞으면 제대로 동작안함 : sort와 마찬가지인듯
- sort 시킨후 reverse 하면됨


17) 배열 요소마다 함수 실행시키기 : Array.prototype.forEach
1
2
3
4
5
6
7
var arr = [1,2,3,4,5,6,7,8,9,10];
 
arr.forEach(function(element, index, array){
     console.log(element + ", " + index + ", " + array);
     if(index === 4)
          break// Syntax Error
});
cs
- 배열 요소마다 어떤 함수를 적용시켜야할 때 forEach 함수를 사용
- forEach 함수의 파라미터 함수(콜백함수 - 배열 요소 하나씩 돌때마다 호출되는 함수) element, index, array를 가짐
- element : 현재 배열 요소
- index : 현재 배열 요소의 배열에서 인덱스
- array : forEach 함수가 적용되고 있는 배열
- index, array 파라미터는 생략해도 됨
- forEach 함수는 예외 발생이외에 중간에 멈출 수 없음 : break 문 안됨


18) 모든 배열 요소가 함수 실행 구문 테스트에 통과하는지 테스트하기 : Array.prototype.every
1
2
3
4
5
6
function isEven(element, index, array){
     return element % 2 == 0;
}
 
var arr = [123456]; // 1에서 멈춤, false
arr.every(isEven);
cs
- every 함수의 인수로 전달되는 함수 실행구문은 불리언(true/false) 결과를 리턴해야함
- every 함수의 인수로 전달되는 콜백함수는 forEach의 파라미터 함수와 같음
- element : 현재 처리 중인 배열 요소
- index : 현재 처리 중인 배열 요소의 인덱스
- array : every가 호출한 배열
- index, array 파라미터는 생략해도 됨
- 모든 요소가 콜백함수의 실행구문(조건)을 통과하지못할 때 false, 통과한다면 true
- 검사 중간 false가 나올 경우 멈추고 결과값을 리턴(&&)


19) 일부 배열 요소가 함수 실행 구문 테스트에 통과하는지 테스트하기 : Array.prototype.some
1
2
3
4
5
6
var arr = [2,5,7,9,11];
 
var isIncludeEven = arr.some(function(element, idx, arr){
    return element%2 === 0;
});
 
cs
- every와는 동일하지만 다름 : every는 true 조건이 &&라면, some은 true 조건이 ||(콜백함수의 실행문)
- 배열 요소 중 1개 이상이 true라면 true를 반환
- 하나라도 true라면 바로 멈추고 true를 반환함
- 입력값을 받고, 배열 내에 입력값이 존재하는지 체크할 때 사용하면 됨


20) 배열 요소 하나의 값으로 합하기 : Array.prototype.reduce / Array.prototype.reduceRight
1
2
3
4
5
6
7
8
9
10
11
12
function add(previous, current, idx, arr){
     return previous + current;
}
 
var arr = [1,2,3,4,5];
var sum = arr.reduce(add);
console.log(sum); // 15
 
var arr2 = [[01], [23], [45]];
arr2.reduce(function(a, b){
     return a.concat(b);
})
cs
- reduce의 파라미터로 콜백함수를 지정함 : 콜백함수가 배열 요소 하나씩 불러와(배열 길이만큼) 더하고 그 결과값을 리턴함
- reduce의 파라미터로 선택사항 초기값 지정할 수 있음 : previousValue에 해당하는 값 지정가능(지정하지않으면 배열 첫번째 요소)
- 콜백함수의 파라미터는 4개가 있음 : previousVal, currentVal, index, array
- previousVal : reduce 초기값(두번째 파라미터) 없다면 배열의 첫번째 요소가 첫번째로 값 지정, 이후 부턴 배열 요소의 합 변수로 쓰임
- currentVal : 현재 배열 요소 중 1개의 값 - 순서대로
- index : 현재 배열 요소의 인덱스
- array : reduce를 호출한 배열
- 합을 계속해서 합치는 것 : 콜백함수는 이벤트큐 - 이벤트루프 - 
- 2차원 배열을 1차원으로 만들기 : concat 함수 활용
- Array.prototype.reduceRight : reduce와 동일하지만 합치는 방향이 거꾸로부터 시작(문자열을 합칠 경우 중요)


21) 배열 요소마다 함수 실행시키기 후 결과를 새로운 배열 삽입 : Array.prototype.map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var arr = [7855476291];
 
var newArr = arr.map(function(currentVal, idx, arr){
     return currentVal + 5;
});
 
console.log(arr); // (5) [78, 55, 47, 62, 91]
console.log(newArr); // (5) [83, 60, 52, 67, 96]
 
 
var objArr = [
     { name"jinbro", age: 26 },
     { name"james", age: 30 },
     { name"brew", age: 81 },
     { name"grand", age: 11 }
]
 
var newObjArr = objArr.map(function(currentObj){
     var newObj = {};
     newObj.name = currentObj.name;
     newObj.age = currentObj.age + 1;
      
     return newObj;
});
cs
- forEach와 같지만 새로운 배열을 생성하는 것에서는 다름
- 뭐 어떤 버프를 주지만 일시적으로 버프를 줄 때? : 새로운 배열을 생성함, 기존 배열은 그대로 유지


22) 배열 요소 중 조건에 맞는 요소만 추려 새로운 배열 만들기 : Array.prototype.filter
1
2
3
4
5
6
7
8
9
10
11
var objArr = [
     { name"jinbro", grade: 87 },
     { name"james", grade : 92 },
     { name"brew", grade : 81 },
     { name"grand", grade : 75 }
]
 
var newObjArr = objArr.filter(function(currentObj){
     return currentObj.grade >= 85;
}); // jinbro와 james만이 점수가 85점 이상이므로 새로운 배열의 요소로 추가됨
 
cs
- every와 비슷하지만 콜백함수 내부 구문(조건 구문)에 맞는 요소만 추려 새로운 배열을 생성하는 것이 다름
- json에서 유효한 값만 골라내기 : 위처럼 무효값을 걸러내어(조건문) 유효값만 골라내기


[배열 확장하기 - 이차원 배열. ... 다차원배열]
- 자바스크립트는 기본적으로 일차원 배열만 지원함
- 액셀 스프레드시트를 생각하면 쉬움 
- 가로 방향(row, 행) / 세로 방향(column, 열)
- row를 셀 때에는 세로 방향 갯수를 세고, column을 셀 때에는 가로 방향 갯수를 세면 됨


이차원배열 : 배열에 배열을 중첩함으로서 구현 가능
1
2
3
4
5
var arr = [];
var rows = 5;
 
for(var i=0; i<5; i++)
     arr[i] = [i, i+1]; // 임의로 배열 요소를 넣음 : 확인을 위해서
cs
- arr[0] : 1행 내용 출력, arr[2][1] : 3행의 두번째 요소 출력


- 행 기준으로 데이터 처리하기 : 사람 기준으로 평균값 내기(임의로 마지막행에 avg 추가)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var grades = [[897778], [768281], [919498]]
var total = 0;
var avg = 0.0;
 
for(var row=0; row<grades.length; row++){
     for(var col=0; col<grades[row].length; col++){
          total += grades[row][col];
     }
     
     avg = (total / grades[row].length).toFixed(2);
     grades[row].push(avg);
 
     total = 0;
     avg = 0.0;
}
 
cs
- 사람 기준(행)으로 데이터를 처리함
- toFixed 함수로 소수점 2자리까지만 표시하도록


- 열 기준으로 데이터 처리하기 : 과목 기준으로 평균값 내기(임의로 새로운 배열에 과목당 avg를 요소로)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var grades = [[897778], [768281], [919498]]
var total = 0;
var avg = 0.0;
var avgGrades = [];
 
for(var col=0; col<grades.length; col++){
     for(var row=0; row<grades[col].length; row++){
          total += grades[row][col];
     }
      avg = (total / grades[col].length).toFixed(2);
      avgGrades[col] = avg;
 
      total = 0;    
      avg = 0.0;
 
}
 
cs
- 과목별 점수를 기준으로 하기때문에 과목별 점수를 큰 기준(반복문 바깥)으로
- 반복문의 순서만 바꿔주면 무엇을 기준으로 하냐가 달라짐


- 길이가 둘쭉날쭉한 배열 : 자바스크립트 배열 행의 길이는 정확하게 알 수 있음(length 프로퍼티)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var grades = [[9785], [928592], [969298100]]
var total = 0;
var avg = 0.0;
 
for(var row=0; row<grades.length; row++){
     for(var col=0; col<grades[row].length; col++){
          total += grades[row][col];
     }     
     avg = (total / grades[row].length).toFixed(2);
 
     grades[row].push(avg)
     total = 0;
     avg = 0.0;
}
 
cs
- 배열 행의 열 길이가 다르다하더라도 배열 객체의 length 프로퍼티가 있기때문에 상관x


[참조자료]
- O'REILLY, 자바스크립트 자료구조와 알고리즘 : http://www.yes24.com/24/goods/14419692?scode=032&OzSrank=1



댓글