10. concat 메소드

LSA·2022년 1월 28일
2

Pre-study

목록 보기
11/18

위코드 사전 스터디를 듣고 쓰는 글입니다.
수업 내용을 참고/인용하여 작성했습니다.

또다른 메소드의 등장,concat()입니다!

concat()

당연한 이야기지만 이 친구와는 다릅니다!
하지만 귀여우니까 냥캣 브금을 들으면서 작업해보아요!

concat() 메서드는 주어진 배열에 기존 배열을 합쳐서 새로운 배열을 반환합니다.
원본 배열은 변하지 않으며 새로운 배열이나 원본 배열을 수정해도 서로 영향을 받지 않습니다.

concatslice와 함께 새로운 배열을 반환하기 때문에, 원본 배열에는 영향을 가하지 않는 메소드네요.
그럼 한번 써보겠습니다.

표현식

만약 우리가 강아지 임시 보호소를 운영한다고 해봅시다.
우리가 데리고 있는 강아지는 총 3마리인데, 여기서 새로 구조된 강아지들이 더 추가된다 하네요.
새로 온 강아지들을 합쳐 봅시다.

let dog1 = ['진돗개','불독','믹스견'];
let dog2 = ['불독','비숑','믹스견','허스키'];

dog1.concat(dog2);
//Array(7) [  "진돗개", "불독", "믹스견", "불독", "비숑", "믹스견", "허스키" ]

이걸로 끝인가요?
네.끝입니다.

맨 앞자리에는 베이스가 될 배열을 부르고, 메소드 안 소괄호에는 합쳐질 배열을 적어줍니다.
잠깐, 그런데 똑같은 불독이 2마리가 된 것을 확인할 수 있습니다.

concat의 특징

같은 불독이라고 해도 각 불독은 제각각 다른 강아지겠죠? concat은 요소의 중복과 상관없이 요소들을 각자 다른 개체로 취급하여 합쳐주기때문에 중복되는 요소를 자동으로 없애주진 않습니다.
종만 같은 것뿐이지 다릅니다.

또다른 유의점

인자를 어떻게 넣어주냐에 따라서, 결과가 달라질 수 있습니다.

const letters = ['a','b','c'];

먼저 letters 배열을 만들어 준 다음,

  • 배열을 변수로 만들어 합체
let addLetter = ['d',['e','f']];
letters.concat(addLetter);
//총 5개의 요소를 가진 Array ['a','b','c','d',['e','f']]가 출력됨
  • 인자에서 배열을 작성해 합체
letters.concat('g',['h','i']);
//총 6개의 요소를 가진 Array [ "a", "b", "c", "g", "h", "i" ]가 출력됨

인자에서 다차원 배열을 만들어주면, 이것을 무시하고 싸그리 letters의 요소로 추가해버리는 현상을 발견할 수 있습니다.

어이없어하는 글쓴이의 모습이다.

예제 1

month1,month2 배열을 concat()을 이용해서 하나의 배열로 합쳐주세요.
아래와 같은 결과가 나와야합니다.

let month1 = ['Jan', 'Feb', 'March', 'Apr', 'May', 'June'];
let month2 = ['July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'];
[ 'July',
  'Aug',
  'Sept',
  'Oct',
  'Nov',
  'Dec',
  'Jan',
  'Feb',
  'March',
  'Apr',
  'May',
  'June' ]

정말 간단하게도 두 배열 중 하나에 concat 메소드만 사용해주면 됩니다.
그런데 July가 맨 앞에 나와야겠네요?

정답

function combineMonth() {
	let newArr = month2.concat(month1)
	return newArr;
}

상식적으로는 1월인 Jan이 먼저 나와야겠지만, 조건에 맞춰 month2의 데이터가 앞줄에 나오도록 해줍니다.

예제 2

num 배열안의 요소들을 concat()을 이용해서 하나의 배열로 합쳐지게 해주세요.
아래와 같은 결과가 나와야 합니다. (힌트: array에서 index로 접근)

let num = [[11, 12, 13], [14, 15, 16], [17, 18, 19]]; 
[ 11, 12, 13, 14, 15, 16, 17, 18, 19 ]

갑자기 또 다차원배열이 나와 조금 정신이 혼미해집니다.
진정하고 위에서 명시했던 concat의 특징들을 떠올려봅니다.

  • concat이 인자로 받는 배열은 직접 쓸 수도 있고, 배열을 변수로 저장해 인자로 건넬 수 있습니다.
  • concat은 기존의 배열에서 합체시키는 것이 아닌, 각 배열의 데이터를 합쳐주어 새로운 배열로 만들어주는 메소드입니다.

정답

function makeNewArr () {
  let newNum = [];
  newNum = newNum.concat(num[0],num[1],num[2]);  
  return newNum
}

한줄씩 해석하자면,

let newNum = [];

concat으로 합친 배열들을 새로 명시해주기 위해 빈 배열인 newNum을 하나 만듭니다.

newNum = newNum.concat(num[0],num[1],num[2]);

newNum은 기존 배열 num

  • 0번째 인덱스 [11, 12, 13]
  • 1번째 인덱스 [14, 15, 16]
  • 2번째 인덱스 [17, 18, 19]
    를 합친 것과 같습니다.(쉼표를 사용하여 배열들을 이어줄 수 있습니다.)
return newNum

이런 newNum 배열을 반환.

예제3

그런데 어느날 우리는 concat으로 합친 배열의 요소들이 중복되면 안되는 상황에 처했습니다.

파스타와 피자의 재료가 배열로 나타나있습니다. 위의 코드를 참고해서 중복된 재료를 뺀 전체 재료의 배열 한 개를만들어주세요.

let pasta = ['tomato', 'basil', 'onion','chicken'];
let pizza = ['tomato', 'cheese', 'onion','olive','beef'];

아래와 같은 결과가 나와야 합니다.

// 중복된 재료를 뺀 전체 재료 
[ 'tomato', 'basil', 'onion', 'chicken', 'cheese', 'olive', 'beef' ]

큰일났습니다.
하지만, 일단 함수부터 만들어두고..
pasta에다가 pizza를 합쳐봅니다.
또한 배열을 반환하기 위해 변수를 만들어줍니다.

function totalIngredients () {
 let both = pasta.concat(pizza)
 // both = ['tomato', 'basil', 'onion','chicken','tomato', 'cheese', 'onion','olive','beef']
 return both
}

중복되는 단어들을 없애기 위해, 저번에 배운 filter함수를 써보기로 합니다.
filter의 문법은?

let newArray = sampleArray.filter(callbackFunction(element, index, array),thisArg);
//element : 요소값
//index : 요소의 인덱스
//array : 사용되는 배열 객체
//thisArg: filter에서 사용될 this 값

여하튼 우리는 재료의 내용을 확인하고, 중복되는 값의 번호를 알아야 하기때문에

  • 요소의 값
  • 요소의 인덱스
    가 필요하므로 callbackFunctionelement,index로 받을 매개변수의 이름만 적어주면 됩니다.

다시 짜던 코드로 돌아와봐요.

function totalIngredients () {
 let both = pasta.concat(pizza)
 //filter 함수 추가
 let useFilter = both.filter(function(name,i){ //both 배열에 filter 메소드를 사용하는데, both의 요소들의 값과 index를 인자로 받아옵니다.
 	return both.indexOf(name) == i //both에서 무언가 반환해야하는데..
 })
 
 return both
}

return both.indexOf(name) == i

응?이건 또 뭐야?
여기서 우리는 또다른 메소드를 만나게 됩니다.

indexOf()?

indexOf()는 스트링에서 특정 문자의 위치를 찾기 위한 함수입니다.

string.indexOf(searchvalue, position)

문자열에서 특정 문자열 (searchvalue)을 찾고, 검색된 문자열이 첫번째로 나타나는 위치 index를 반환해줍니다.
position은 선택 입력 사항이며, 어느 위치에서부터 검색을 시작할건지를 지정해줍니다.
찾는 문자열이 없으면 -1을 반환하는 속성을 가지고 있으며,대소문자를 구분합니다.

참고 사이트 :https://hianna.tistory.com/379

다시 돌아와서..

return both.indexOf(name) == i
그러니까 이것을 해석하면, 매개변수로 받은 both배열의 요소 값들 중 인덱스 번호가 중복되는지 체크하는 기능인거에요. 한번 볼게요.

 console.log(both.indexOf(name))
0 //'tomato'
1 //'basil'
2 //'onion'
3 //'chicken'
0 //'tomato'
5 //'cheese'
2 //'onion'
7 //'olive'
8 //'beef'

정말로 같은 이름을 가진 요소들의 인덱스가 같은 숫자로 중복되는 것을 확인했습니다!

function totalIngredients () {
 let both = pasta.concat(pizza)
 //filter 함수 추가
 let useFilter = both.filter(function(name,i){ //both 배열에 filter 메소드를 사용하는데, both의 요소들의 값과 index를 인자로 받아옵니다.
 	return both.indexOf(name) == i //both에서 이름이 중복되는 인덱스들은 전부 제외한 값을 반환합니다.
 })
 
 return both
}

자, 이걸로 끝일까요? 아닙니다. 한 줄만 더 추가해주면 됩니다.

function totalIngredients () {
 let both = pasta.concat(pizza)
 //filter 함수 추가
 let useFilter = both.filter(function(name,i){ //both 배열에 filter 메소드를 사용하는데, both의 요소들의 값과 index를 인자로 받아옵니다.
 	return both.indexOf(name) == i //both에서 이름이 중복되는 인덱스들은 전부 제외한 값을 반환합니다.
 })
 both = useFilter //배열 both와 배열 useFilter의 값을 동일하게 맞춰줍니다.
 return both
}

우리는 변수를 총 2개 사용했잖아요.

정답

function totalIngredients () {
 let both = pasta.concat(pizza)
 let useFilter = both.filter(function(name,i){
 	return both.indexOf(name) == i
 });
 both = useFilter
 return both
}

긴 여정을 끝내고 드디어 완성했습니다.
여기서 함수를 호출해주거나 콘솔로 출력해보면, 예제에서 원하는 답이 나오는 것을 알 수 있어요.

마무리

사실 예제 3의 정답은, 더 간편하게 작성할 수 있습니다.

function totalIngredients () {
 let both = pasta.concat(pizza)
 let oneIng = both.filter((name,index)=>both.indexOf(name)==index)
 both = oneIng
 return both
}


기존의 function을 사용하던 문법이랑 굉장히 다른데 대체 뭐죠?
그것에 대해선 다음 글에 포스팅해보겠습니다.

profile
진짜 간단하게 작성한 TIL 블로그

0개의 댓글