본문 바로가기
내일배움 정리/JS 문법 공부

배열

by GREEN나무 2024. 12. 3.
728x90

update

24.12.14 - slice 수정

24.12.13 - sort 수정

 

 

 

- 참고

arr.length : 배열의 길이. 1부터 시작

 

...arr   배열을 풀어야 할 때 배열 이름 앞에 ...을 붙이세요

function solution(N) {
    return [...String(N)].reduce((sum, digit) => sum + +digit, 0);
}

 


배열 선언 및 초기화

  1. 배열 선언
  2. let arr = []; // 빈 배열 let numbers = [1, 2, 3, 4, 5]; // 숫자 배열 let mixed = [1, "hello", true, { key: "value" }, [1, 2]]; // 혼합형 배열
  3. Array 생성자 사용
  4. let arr = new Array(); // 빈 배열 let numbers = new Array(10); // 길이가 10인 빈 배열 let predefined = new Array(1, 2, 3); // [1, 2, 3]

기본 배열 메서드

1. 요소 접근 및 변경

let arr = [10, 20, 30];
console.log(arr[0]); // 10
arr[1] = 25; // 배열의 두 번째 요소 변경
console.log(arr); // [10, 25, 30]

2. 배열 길이 확인

let arr = [1, 2, 3];
console.log(arr.length); // 3

3. 요소 추가/제거

  • push: 끝에 요소 추가
  • pop: 끝에서 요소 제거
  • unshift: 앞에 요소 추가
  • shift: 앞에서 요소 제거
let arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4]
arr.pop(); // [1, 2, 3]
arr.unshift(0); // [0, 1, 2, 3]
arr.shift(); // [1, 2, 3]

배열 순회

for 루프

let arr = [1, 2, 3]; 
for (let i = 0; i < arr.length; i++) {
   console.log(arr[i]); 
}

 

for...of

for (let value of arr) {
   console.log(value); 
}

 

forEach

arr.forEach((value, index) => {
   console.log(index, value); 
});

배열 변환 및 필터링(새로운 배열 만들기)

map: 각 요소를 변환하여 새 배열 생성

let numbers = [1, 2, 3]; 
let squared = numbers.map(num => num ** 2); 
console.log(squared); // [1, 4, 9]

 

filter: 조건을 만족하는 요소만 필터링

let numbers = [1, 2, 3, 4]; 
let evens = numbers.filter(num => num % 2 === 0); 
console.log(evens); // [2, 4]

 

reduce: 누적 계산

뒤에 붙은 0은 acc의 초기값

let numbers = [1, 2, 3, 4]; 
let sum = numbers.reduce((acc, curr) => acc + curr, 0); 
console.log(sum); // 10

https://miiingo.tistory.com/365

   

repeat : 주어진 문자열의 지정된 수만큼 복사본을 포함하는 새 문자열을 반환합니다.

 매개변수는 양의 정수여야 합니다.

// "반복문자열"repeat(count)
"abc".repeat(2); // 'abcabc'

 

이런 식으로도 사용 가능

function solution(n) {
    return "수박".repeat(Math.floor(n / 2)) + (n % 2 === 1 ? "수" : "");
}
console.log(solution(3)); // "수박수"

배열 정렬

sort: 배열 정렬

  • 기본적으로 요소를 문자열로 취급하며 유니코드 순서대로 정렬합니다.
  • 다양한 상황에서 compareFunction을 활용하여 맞춤 정렬이 가능합니다.
    1. 기본 정렬은 문자열 기준이며 유니코드 순서대로 수행됩니다.
    2. 숫자 정렬 시 compareFunction을 반드시 사용해야 합니다.
    3. 2차원 배열과 객체는 특정 요소나 속성을 기준으로 맞춤 정렬이 가능합니다.
    4. 숫자나 객체를 정렬할 때는 compareFunction 사용.
    5. 문자열 정렬 시 localeCompare()를 활용하면 대소문자 구분 없는 정렬도 가능.

 


1. 기본 문법

arr.sort([compareFunction]);
  • compareFunction 생략 시: 요소들은 문자열로 취급되어 유니코드 순서로 정렬.
  • compareFunction 사용 시: 정렬 순서를 직접 정의 가능 .
    • 반환 값이 > 0: a는 b 뒤에 위치
    • 반환 값이 < 0: a는 b 앞에 위치
    • 반환 값이 0: 순서 변경 없음

2. 문자열 정렬

1. 오름차순 정렬

let arr = ["a", "d", "z", "p", "j", "c", "k", "s"];
arr.sort();
console.log(arr); // ['a', 'c', 'd', 'j', 'k', 'p', 's', 'z']

2. 내림차순 정렬

let strArray = ["BA", "BB", "AA", "AB", "CB", "CA"];
strArray.sort((a, b) => (a > b ? -1 : a < b ? 1 : 0));
console.log(strArray); // ["CB", "CA", "BB", "BA", "AB", "AA"]
let strArray = ["BA", "BB", "AA", "AB", "CB", "CA"];
strArray.sort((a, b) => b.localeCompare(a));
console.log(strArray); // ["CB", "CA", "BB", "BA", "AB", "AA"]

 

파라미터

  1. compareFunction(옵션): 정렬 순서를 정의하는 함수.
    • a, b를 입력받아 다음을 결정:
      • 음수 반환: a가 b보다 앞.
      • 양수 반환: b가 a보다 앞.
      • 0 반환: 순서 유지.

리턴값

  • 원본 배열(arr)을 정렬하며, 정렬된 배열을 리턴.
  • 주의: 원본 배열이 변경됨.

3. 내림차순, 대문자가 소문자보다 앞에 오게 정렬

 사용자 지정 정렬 함수를 사용

const arrStr = ['a', 'B', 'C', 'd', 'E', 'f'];

arrStr.sort((a, b) => {
  // 알파벳 내림차순으로 정렬
  if (a.toLowerCase() > b.toLowerCase()) return -1;
  if (a.toLowerCase() < b.toLowerCase()) return 1;

  // 대소문자 우선 순위 설정 (대문자가 소문자보다 앞에)
  if (a < b) return -1;
  if (a > b) return 1;

  return 0; // 동일한 경우
});

console.log(arrStr);
// 출력 예: ['f', 'd', 'a', 'E', 'C', 'B']
  1. toLowerCase()로 문자를 소문자로 변환한 후 알파벳 순서를 기준으로 내림차순 정렬.
  2. 동일한 알파벳일 경우, ASCII 값 비교를 통해 대문자가 소문자보다 앞에 오도록 설정.
    • JavaScript에서 대문자는 소문자보다 작은 ASCII 값을 가짐.

 

4. 대소문자 구분 없이 문자정렬

    대소문자 구분 없는 문자열 정렬은 localeCompare 활용.

오름차순

const words = ['Banana', 'apple', 'Cherry'];
words.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
console.log(words); // ['apple', 'Banana', 'Cherry']

내림차순

words.sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase()));
console.log(words); // ['Cherry', 'Banana', 'apple']

 

 


 

3. 숫자 정렬

숫자, 객체 정렬 시 비교 함수(compareFunction) 필요.

 

1. 한 자리 숫자 정렬 (문자열 취급)

let arr = [1, 4, 6, 8, 5, 3, 7];
arr.sort();
console.log(arr); // [1, 3, 4, 5, 6, 7, 8]

 

2. 오름차순 정렬

  • a - b가 음수면 a가 b보다 앞.
let arr = [13, 46, 52, 36, 75, 3];
arr.sort((a, b) => a - b);
console.log(arr); // [3, 13, 36, 46, 52, 75]

 

3. 내림차순 정렬

  • b - a를 이용.
let arr = [13, 46, 52, 36, 75, 3];
arr.sort((a, b) => b - a);
console.log(arr); // [75, 52, 46, 36, 13, 3]

4. 2차원 배열 정렬

  • 특정 인덱스를 기준으로 정렬
const arr = [
  [10, 2],
  [7, 8],
  [3, 3],
  [-1, 3],
  [99, 99],
  [-10, 10],
];

arr.sort((a, b) => a[1] - b[1]); // 두 번째 요소 기준 오름차순
console.log(arr);
// [ [ 10, 2 ], [ 3, 3 ], [ -1, 3 ], [ 7, 8 ], [ -10, 10 ], [ 99, 99 ] ]
  • 내림차순 정렬
const arr = [
  [2, 9, 2],
  [-1, -2, -3],
  [0, 3, 3],
  [12, -1, 6],
  [9, 10, 11],
];

arr.sort((a, b) => b[2] - a[2]); // 세 번째 요소 기준 내림차순
console.log(arr);
// [ [ 9, 10, 11 ], [ 12, -1, 6 ], [ 0, 3, 3 ], [ 2, 9, 2 ], ... ]

5. 객체 정렬

  • 객체의 특정 속성을 기준으로 정렬
  • 숫자, 객체 정렬 시 비교 함수(compareFunction) 필요.

예: 가격(price)을 기준으로 오름차순

const items = [
  { name: 'apple', price: 50 },
  { name: 'banana', price: 30 },
  { name: 'cherry', price: 70 }
];

items.sort((a, b) => a.price - b.price);
console.log(items);
// [
//   { name: 'banana', price: 30 },
//   { name: 'apple', price: 50 },
//   { name: 'cherry', price: 70 }
// ]

내림차순

items.sort((a, b) => b.price - a.price);
console.log(items);
// [
//   { name: 'cherry', price: 70 },
//   { name: 'apple', price: 50 },
//   { name: 'banana', price: 30 }
// ]

reverse: 배열 순서 뒤집기

let arr = [1, 2, 3];  
console.log(arr.reverse()); // [3, 2, 1]

 


 배열 탐색

find: 조건을 만족하는 첫 번째 요소 찾기

let arr = [5, 12, 8, 130, 44]; 
let found = arr.find(num => num > 10); 
console.log(found); // 12

 

findIndex : 조건을 만족하는 첫 번째 요소의 인덱스 찾기

    조건을 만족하는 요소가 없으면 -1을 반환합니다.

let arr = [10, 20, 30, 40]; 
let index = arr.findIndex(num => num > 25); 
console.log(index); // 2 (30은 25보다 큼) 
console.log(arr.findIndex(num => num > 50)); // -1 (조건을 만족하는 요소 없음)
 

indexOf / includes

indexOf : 배열이나 문자열에서 특정 값을 찾고, 그 첫 번째 발생 위치의 인덱스를 반환합니다.
          찾는 값이 없으면 -1을 반환합니다. 

includes : 배열이나 문자열에서 특정 값을 찾고, 있으면 true  없으면 false를 방환합니다.

let arr = [1, 2, 3, 4];
console.log(arr.indexOf(3)); // 2 일치하는 값의 자리를 반환
console.log(arr.includes(5)); // false 포함여부 boolen값으로 반환

 

lastIndexOf : 배열이나 문자열에서 특정 값을 찾고, 마지막으로 발생한 위치의 인덱스를 반환합니다.

         찾는 값이 없으면 -1을 반환합니다.

   배열 예제

let arr = [10, 20, 30, 20]; 
console.log(arr.lastIndexOf(20)); // 3 (마지막 20의 인덱스) 
console.log(arr.lastIndexOf(50)); // -1 (50은 배열에 없음)

 

   문자열 예제

let str = "hello world, hello!"; 
console.log(str.lastIndexOf("hello")); // 13 (마지막 "hello"의 시작 인덱스)
console.log(str.lastIndexOf("JavaScript")); // -1 (존재하지 않음)

 

Array.some()

some() 메서드는 배열의 요소 중 적어도 하나가 주어진 판별 함수를 통과하는지 확인합니다.

조건을 만족하는 요소가 하나라도 있으면 true를 반환, 없다면 false를 반환합니다.

배열 자체를 변경하지 않습니다.

// 화살표 함수
some((element) => { /* … */ })
some((element, index) => { /* … */ })
some((element, index, array) => { /* … */ })

// 콜백 함수
some(callbackFn)
some(callbackFn, thisArg)

// 인라인 콜백 함수
some(function (element) { /* … */ })
some(function (element, index) { /* … */ })
some(function (element, index, array) { /* … */ }, thisArg)

매개변수:

  1. callbackFn:
    • 배열의 각 요소에 대해 실행되는 함수.
    • 인자:
      • element: 현재 요소.
      • index: 현재 요소의 인덱스.
      • array: some()을 호출한 배열.
  2. thisArg (선택):
    • callbackFn을 실행할 때 사용할 this 값.

반환값:

  • 배열의 요소 중 하나라도 callbackFn에서 참(true)을 반환하면 true.
  • 모든 요소가 거짓(false)일 경우 false.

특징

  1. 순회 멈춤:
    조건을 만족하는 요소를 찾으면 바로 순회를 멈추고 true를 반환합니다.
  2. 희소 배열 지원:
    값이 없는 빈 슬롯은 무시됩니다.
  3. 배열의 원본 유지:
    배열을 변경하지 않습니다.
  4. 일반 객체에서도 사용 가능:
    배열이 아닌 객체에서도 Array.prototype.some을 호출하여 사용할 수 있습니다. (길이와 키 속성만 있으면 됨)
// 조건 테스트:
[2, 5, 8, 1, 4].some((x) => x > 10); // false 
[12, 5, 8, 1, 4].some((x) => x > 10); // true

// 값 포함 여부 확인:
const fruits = ["apple", "banana", "mango"]; 
fruits.some((fruit) => fruit === "banana"); // true 
fruits.some((fruit) => fruit === "grape"); // false

// 불리언 변환:
const TRUTHY_VALUES = [true, "true", 1]; 
function getBoolean(value) {
  return TRUTHY_VALUES.some((t) => t === value);
} 
getBoolean("true"); // true
getBoolean("false"); // false

// 희소 배열 사용:
console.log([1, , 3].some((x) => x === undefined)); // false

// 배열이 아닌 객체에서 사용:
const arrayLike = { length: 3, 0: "a", 1: "b", 2: "c" }; 
Array.prototype.some.call(arrayLike, (x) => x === "b"); // true

 


배열 병합 및 슬라이싱

concat: 배열 병합

let arr1 = [1, 2]; let arr2 = [3, 4]; 
let merged = arr1.concat(arr2); 
console.log(merged); // [1, 2, 3, 4]

 

slice: 배열의 일부를 추출

let arr = [1, 2, 3, 4]; 
let sliced = arr.slice(1, 3); 
console.log(sliced); // [2, 3]

 

- 문자열에서 slice

  • slice() 메서드는 문자열의 일부를 추출하여 새로운 문자열로 반환합니다.
  • 원래 문자열은 수정되지 않습니다.
  • 추출 범위를 벗어나는 인덱스가 사용되더라도 오류는 발생하지 않고 빈 문자열 또는 가능한 범위를 반환.
slice(indexStart)
slice(indexStart, indexEnd)

indexStart

  • 추출할 시작 위치를 지정합니다(0부터 시작하는 인덱스).
  • indexStart >= str.length이면 빈 문자열 반환.
  • 양수: 문자열의 시작에서부터 해당 위치까지 계산.
  • 음수: 문자열의 끝에서부터 뒤로 계산.(-1부터 시작)

indexEnd(생략 가능)

  • 추출을 멈출 위치를 지정합니다(포함되지 않음).
  • 양수: 문자열의 시작에서 해당 위치까지 계산.
  • 음수: 문자열의 끝에서부터 뒤로 계산. (-1부터 시작)
  • 생략하면 문자열의 끝까지 추출.

1. 기본 사용법

const str = "The morning is upon us.";
console.log(str.slice(1, 8));  // "he morn"
console.log(str.slice(4, -2)); // "morning is upon u"
console.log(str.slice(12));    // "is upon us."
console.log(str.slice(30));    // "" (빈 문자열)

 

2. 음수 인덱스 사용

const str = "The morning is upon us.";
console.log(str.slice(-3));       // "us."
console.log(str.slice(-3, -1));   // "us"
console.log(str.slice(11, -7));  // " is u"
console.log(str.slice(-11, -7)); // " is "
console.log(str.slice(0, -1));    // "The morning is upon us"
console.log(str.slice(4, -1));    // "morning is upon us"

 


배열 slice

  •  배열 또는 유사 배열 객체의 일부를 추출하여 얕은 복사본으로 반환하는 도구
  • 원본 배열은 절대 수정되지 않습니다.
  • 새로운 배열 객체로, 원본 배열에서 선택된 요소들을 반환합니다.

1. 기본

slice()
slice(start)
slice(start, end)
  • start (선택사항): 추출 시작 인덱스(0 기반). 음수일 경우, 배열 끝에서부터 계산.
  • end (선택사항): 추출 종료 인덱스. 포함되지 않음. 음수일 경우 배열 끝에서부터 계산.
const fruits = ["Apple", "Banana", "Orange", "Mango"];
// 기본
console.log(fruits.slice(1, 3)); // ['Banana', 'Orange']
// end 매개변수 생략
console.log(fruits.slice(2)); // ['Orange', 'Mango']
// 음수 인덱스 사용
console.log(fruits.slice(-2)); // ['Orange', 'Mango']
// 양수 및 음수 인덱스 혼합
console.log(fruits.slice(1, -1)); // ['Banana', 'Orange']

 

2. 객체 배열 슬라이싱

const car = { color: "red" };
const array = [car, "other"];
const newArray = array.slice(0, 1);

car.color = "blue";
console.log(newArray[0].color); // 'blue'

배열 유사 객체 슬라이싱

const arrayLike = { length: 3, 0: "a", 1: "b", 2: "c" };
console.log(Array.prototype.slice.call(arrayLike)); // ['a', 'b', 'c']

배열 변환 유틸리티

const slice = Function.prototype.call.bind(Array.prototype.slice);

function convertArgsToArray() {
  return slice(arguments);
}
console.log(convertArgsToArray(1, 2, 3)); // [1, 2, 3]

3. 희소 배열 처리

console.log([1, , 3, 4].slice(1, 3)); // [empty, 3]

 

 


splice: 배열 수정 (요소 추가/삭제)

배열에서 요소를 추가하거나 제거하거나 교체하는 데 사용

  1. 배열을 직접 수정합니다(원본 배열 변경).
  2. 추가와 삭제를 동시에 수행할 수 있습니다.
  • 성능: .splice()는 배열 크기에 따라 성능에 영향을 줄 수 있습니다. 특히, 많은 요소가 포함된 배열에서 중간 요소를 제거하면 뒤의 모든 요소가 이동합니다.
  • 원본 배열이 변경되므로 불변성이 중요한 경우 slice()나 다른 메서드를 고려해야 합니다.
array.splice(start, deleteCount, item1, item2, ...);
  1. start (필수):
    • 변경을 시작할 배열의 인덱스를 지정합니다.
    • 양수: 해당 인덱스부터 시작.
    • 음수: 배열의 끝에서부터 역으로 계산.
  2. deleteCount (선택):
    • 배열에서 제거할 요소의 개수를 지정합니다.
    • 0이면 아무 것도 삭제하지 않습니다(추가만 수행).
    • 생략하면 start부터 배열의 끝까지 모든 요소를 삭제합니다.
  3. item1, item2, ... (선택):
    • 배열에 추가할 요소들을 지정합니다.
    • 삭제 대신 새 요소를 삽입하거나 기존 요소를 교체할 때 사용됩니다.
let arr = [1, 2, 3, 4]; 
arr.splice(1, 2, 5, 6); // 1번 인덱스에서 2개 제거, 5와 6 추가 
console.log(arr); // [1, 5, 6, 4]

    1. 요소 삭제

let fruits = ["apple", "banana", "cherry", "date"];
let removed = fruits.splice(1, 2);  // 인덱스 1부터 2개 제거

console.log(fruits); // ["apple", "date"]
console.log(removed); // ["banana", "cherry"]

    2. 요소 추가

let fruits = ["apple", "date"];
fruits.splice(1, 0, "banana", "cherry");  // 인덱스 1에 추가

console.log(fruits); // ["apple", "banana", "cherry", "date"]

    3. 요소 교체

let fruits = ["apple", "banana", "cherry"];
fruits.splice(1, 1, "grape");  // 인덱스 1의 요소를 "grape"로 교체

console.log(fruits); // ["apple", "grape", "cherry"]

    4. 끝에서부터 요소 삭제

let fruits = ["apple", "banana", "cherry"];
fruits.splice(-1, 1);  // 끝에서부터 1개 제거

console.log(fruits); // ["apple", "banana"]

배열 수정

스프레드 문법과 객체.assign을 활용해 조건부로 속성을 병합하는 방식

export const updatePlayer = (req, res) => {
    try {
        const { name } = req.params;
        const { speed, shooting, grade } = req.body;
        if (!name) return handleError(res, 400, "Player name is required.");

        const player = players.find((p) => p.name === name);
        if (!player) return handleError(res, 404, "Player not found.");

        Object.assign(player, { ...(speed && { speed }), ...(shooting && { shooting }), ...(grade && { grade }) });
        res.status(200).json(player);
    } catch {
        handleError(res, 500, "Failed to update player");
    }
};
더보기

 


코드 동작 설명

  1. 요청에서 파라미터와 데이터 추출:
    • req.params에서 name을 가져옵니다. 이는 URL 경로의 파라미터입니다.
    • req.body에서 speed, shooting, grade 값을 추출합니다. 이는 클라이언트가 보낸 JSON 데이터입니다.
    const { name } = req.params;
    const { speed, shooting, grade } = req.body;
    
  2. 유효성 검사:
    • name이 없으면 에러를 반환합니다.
    • players 배열에서 해당 이름의 플레이어를 찾습니다.
    • 찾지 못하면 404 에러를 반환합니다.
    if (!name) return handleError(res, 400, "Player name is required.");
    const player = players.find((p) => p.name === name);
    if (!player) return handleError(res, 404, "Player not found.");
    
  3. 업데이트 수행:
    • Object.assign을 사용하여 기존 player 객체를 업데이트합니다.
    • 조건부로 제공된 데이터(speed, shooting, grade)만 병합됩니다.
    • 이를 위해 스프레드 문법을 사용해 개별 속성을 분리하고, 조건이 참일 때만 객체로 추가합니다.
    Object.assign(
        player,
        {
            ...(speed && { speed }),
            ...(shooting && { shooting }),
            ...(grade && { grade })
        }
    );
    
  4. 응답 반환:
    • 업데이트된 player 객체를 JSON 형식으로 반환합니다.
    • 상태 코드는 200입니다.
    res.status(200).json(player);
    
  5. 에러 처리:
    • 실행 중 문제가 발생하면 상태 코드 500과 함께 에러 메시지를 반환합니다.
    catch {
        handleError(res, 500, "Failed to update player");
    }
    

핵심 코드 분석

1. Object.assign

Object.assign은 하나 이상의 객체를 병합해 기존 객체를 업데이트하거나 새로운 객체를 생성할 때 사용됩니다.

Object.assign(target, source1, source2, ...);
  • target: 병합의 대상이 되는 객체.
  • source: 병합할 속성들을 가진 객체.

이 코드에서 Object.assign(player, {...})는 player 객체에 새로운 속성들을 추가하거나 기존 속성을 덮어씁니다.


2. 스프레드 문법 ...

...는 객체나 배열의 요소를 "펼쳐서" 새로운 객체/배열을 생성하는 문법입니다.

조건부 속성 추가

...(speed && { speed })
  • 조건 speed가 truthy일 때만 { speed: speed }라는 객체를 생성하고, 이를 펼쳐서 병합합니다.
  • 만약 speed가 undefined거나 null이라면 아무 것도 병합되지 않습니다.

전체 코드

{
   ...(speed && { speed }),     // speed가 있으면 { speed: speed }
   ...(shooting && { shooting }), // shooting이 있으면 { shooting: shooting }
   ...(grade && { grade })      // grade가 있으면 { grade: grade }
}
  • 결과적으로 speed, shooting, grade 중 클라이언트가 제공한 값만 병합됩니다.

3. 배열과 객체의 동작

players는 배열이므로, players.find를 통해 특정 조건에 맞는 객체 참조를 가져옵니다.
이후 Object.assign으로 이 참조된 객체의 내용을 직접 변경합니다. 배열 자체는 수정되지 않고, 해당 객체만 업데이트됩니다.


장점

  1. 조건부 업데이트:
    • 제공된 속성만 업데이트하며, 불필요한 데이터 변경을 방지합니다.
  2. 간결성:
    • 스프레드 문법과 Object.assign으로 복잡한 업데이트를 한 줄로 처리합니다.
  3. 원본 객체 수정:
    • player는 players 배열의 원본 참조이기 때문에, Object.assign으로 업데이트하면 배열의 해당 객체도 즉시 반영됩니다.

스프레드 문법 대신 if문을 사용

export const updatePlayer = (req, res) => {
    const { name } = req.params;
    const { speed, shooting, grade } = req.body;
    const player = players.find((p) => p.name === name);

    if (!player) return res.status(404).json({ message: "Player not found" });

    if (speed) player.speed = speed;
    if (shooting) player.shooting = shooting;
    if (grade) player.grade = grade;

    res.json(player);
};



Object.assign 없이 새로운 객체를 생성하여 기존 객체를 업데이트

1. 스프레드 문법을 사용

스프레드 문법을 사용하여 원래 객체와 업데이트할 속성들을 병합하여 새 객체를 생성합니다.

const updatedPlayer = {
    ...player,
    ...(speed && { speed }),
    ...(shooting && { shooting }),
    ...(grade && { grade }),
};
  • ...player: 기존 객체의 모든 속성을 복사합니다.
  • 조건부 병합:
    • speed && { speed }처럼 값이 존재할 때만 속성을 추가합니다.
  • 기존 player는 유지되고, updatedPlayer라는 새 객체가 생성됩니다.

2. Object.keys와 forEach 사용

수동으로 객체를 순회하며 조건에 맞는 속성만 추가합니다.

const updatedPlayer = { ...player }; // 기존 객체 복사
['speed', 'shooting', 'grade'].forEach((key) => {
    if (req.body[key]) updatedPlayer[key] = req.body[key];
});
  • 속성 리스트: 업데이트할 가능성이 있는 속성 목록을 배열로 정의.
  • 조건부 추가: req.body에 값이 있는 속성만 새로운 객체에 추가.

3. for...in 반복문 사용

for...in 문을 사용하여 동적으로 속성을 검사하고 추가할 수 있습니다.

const updatedPlayer = { ...player }; // 기존 객체 복사
for (const key in req.body) {
    if (['speed', 'shooting', 'grade'].includes(key) && req.body[key]) {
        updatedPlayer[key] = req.body[key];
    }
}
  • 유효성 검사:
    • key가 허용된 속성(speed, shooting, grade)인지 확인.
    • 값이 존재할 때만 추가.

4. reduce를 활용한 함수형 방식

reduce를 사용하여 유효한 속성만 새로운 객체에 추가합니다.

const updatedPlayer = ['speed', 'shooting', 'grade'].reduce((acc, key) => {
    if (req.body[key]) acc[key] = req.body[key];
    return acc;
}, { ...player });
  • 초기값: player의 복사본을 초기값으로 사용.
  • 조건부 추가: req.body에 값이 있는 속성만 acc 객체에 추가.

5. 깊은 병합을 위한 유틸 함수 활용

여러 단계로 중첩된 객체를 병합하려면 커스텀 함수를 사용할 수 있습니다.

function merge(target, source) {
    const result = { ...target };
    for (const key in source) {
        if (source[key] !== undefined) {
            result[key] = source[key];
        }
    }
    return result;
}

const updatedPlayer = merge(player, { speed, shooting, grade });
  • merge 함수:
    • 기존 객체(target)과 새 데이터(source)를 병합.
    • 값이 undefined가 아닌 경우에만 병합.

비교

방법 장점 단점

스프레드 문법 간결하고 가독성이 높음 업데이트할 속성이 많으면 코드가 길어질 수 있음
Object.keys + forEach 동적으로 처리 가능, 코드 관리 용이 반복문을 사용해 약간 복잡해질 수 있음
for...in 반복문 유연하게 속성 검사 가능 배열 순회보다 조금 더 느릴 수 있음
reduce 함수형 방식으로 간결한 처리 가능 초심자에게는 약간 난해할 수 있음
유틸 함수 사용 재사용 가능, 유연한 병합 가능 커스텀 함수 정의가 필요

 


문자열, 숫자  ↔  배열

join: 배열을 문자열로 결합

let arr = ["Hello", "World"]; 
console.log(arr.join(" ")); // "Hello World"

 

split은 문자열(String)을 특정 구분자를 기준으로 분리하여 배열(Array)로 반환하는 메서드입니다. 주로 문자열을 배열로 변환할 때 사용됩니다.

string.split(separator, limit)
  • separator: 문자열을 분리하는 기준이 되는 구분자 (필수).
    • 구분자로 문자열이나 정규식을 사용할 수 있습니다.
    • separator를 지정하지 않으면 문자열 전체가 하나의 요소로 포함된 배열을 반환합니다.
  • limit: 분리 후 반환할 배열의 최대 길이 (옵션).
    • 이 값을 지정하면 배열의 요소 개수가 limit을 초과하지 않습니다.

   기본 

// 기본 예제
let str = "apple,banana,cherry";
let arr = str.split(",");
console.log(arr); // ["apple", "banana", "cherry"]

// 공백을 기준으로 분리
let sentence = "Hello World! How are you?";
let words = sentence.split(" ");
console.log(words); // ["Hello", "World!", "How", "are", "you?"]

//구분자를 빈 문자열로 설정 : 문자열의 각 문자를 개별 요소로 나눌 수 있습니다.
let str = "hello";
let chars = str.split("");
console.log(chars); // ["h", "e", "l", "l", "o"]

 

limit 사용

let str = "one,two,three,four,five";
let arr = str.split(",", 3); // 3개의 요소까지만 반환
console.log(arr); // ["one", "two", "three"]

 

정규식을 사용한 분리

  • 정규식을 사용하면 더 복잡한 패턴으로 문자열을 분리할 수 있습니다.
let str = "apple123banana456cherry";
let arr = str.split(/\d+/); // 숫자를 기준으로 분리
console.log(arr); // ["apple", "banana", "cherry"]

 

구분자를 지정하지 않는 경우

  • 구분자를 생략하면 문자열 전체를 하나의 배열 요소로 반환합니다.
let str = "hello world";
let arr = str.split();
console.log(arr); // ["hello world"]

 

응용: 문장 단위 분리

let text = "This is sentence one. Here is sentence two. And finally, sentence three.";
let sentences = text.split(". ");
console.log(sentences);
// ["This is sentence one", "Here is sentence two", "And finally, sentence three."]

 

 

 

 


참고

 

문자 정렬 : https://yooneeee.tistory.com/17

 

 

 

 

 

 

 

'내일배움 정리 > JS 문법 공부' 카테고리의 다른 글

화살표함수(작성중)  (0) 2024.12.03
형변환, 숫자의 진법변환  (0) 2024.12.03
Math메서드(method)  (1) 2024.12.03
연산 기호 - 같다, 같지 않다 (==, ===, !=, !==  (0) 2024.12.03
input 받기  (0) 2024.12.03