Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 125 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,39 @@
const books = [
{ title: "어린왕자", author: "생텍쥐페리", year: 1943, category: "소설", price: 12000 },
{ title: "1984", author: "조지 오웰", year: 1949, category: "소설", price: 15000 },
{ title: "수학의 정석", author: "홍성대", year: 1966, category: "교육", price: 20000 },
{ title: "코딩 테스트", author: "나동빈", year: 2021, category: "교육", price: 32000 },
{ title: "해리포터", author: "J.K. 롤링", year: 1997, category: "소설", price: 18000 },
{
title: '어린왕자',
author: '생텍쥐페리',
year: 1943,
category: '소설',
price: 12000,
},
{
title: '1984',
author: '조지 오웰',
year: 1949,
category: '소설',
price: 15000,
},
{
title: '수학의 정석',
author: '홍성대',
year: 1966,
category: '교육',
price: 20000,
},
{
title: '코딩 테스트',
author: '나동빈',
year: 2021,
category: '교육',
price: 32000,
},
{
title: '해리포터',
author: 'J.K. 롤링',
year: 1997,
category: '소설',
price: 18000,
},
];

// ─────────────────────────────────────────────
Expand All @@ -19,7 +49,9 @@ const books = [
* getTitlesByCategory(books, "소설") // → ["어린왕자", "1984", "해리포터"]
*/
function getTitlesByCategory(books, category) {
// 여기를 작성하세요
return books
.filter((book) => book.category === category)
.map((book) => book.title);
}

/**
Expand All @@ -31,7 +63,9 @@ function getTitlesByCategory(books, category) {
* getTotalPriceAbove(books, 15000) // → 85000
*/
function getTotalPriceAbove(books, threshold) {
// 여기를 작성하세요
return books
.filter((book) => book.price >= threshold)
.reduce((acc, book) => acc + book.price, 0);
}

/**
Expand All @@ -42,7 +76,7 @@ function getTotalPriceAbove(books, threshold) {
* isAllSameCategory([{ category: "소설" }, { category: "소설" }], "소설") // → true
*/
function isAllSameCategory(books, category) {
// 여기를 작성하세요
return books.every((book) => book.category === category);
}

// ─────────────────────────────────────────────
Expand All @@ -58,7 +92,9 @@ function isAllSameCategory(books, category) {
* formatBookLabel({ title: "어린왕자", author: "생텍쥐페리" }) // → "어린왕자 - 생텍쥐페리"
*/
function formatBookLabel(book) {
// 여기를 작성하세요
const { title, author } = book;

return `${title} - ${author}`;
}

/**
Expand All @@ -69,7 +105,9 @@ function formatBookLabel(book) {
* const { first, rest } = splitFirstAndRest(books)
*/
function splitFirstAndRest(books) {
// 여기를 작성하세요
const [first, ...rest] = books;

return { first, rest };
}

/**
Expand All @@ -81,7 +119,8 @@ function splitFirstAndRest(books) {
* omitPrice({ title: "어린왕자", price: 12000 }) // → { title: "어린왕자" }
*/
function omitPrice(book) {
// 여기를 작성하세요
const { price, ...rest } = book;
return rest;
}

// ─────────────────────────────────────────────
Expand All @@ -96,7 +135,17 @@ function omitPrice(book) {
* // → Map { "소설" => ["어린왕자", "1984", "해리포터"], "교육" => [...] }
*/
function groupByCategory(books) {
// 여기를 작성하세요
const result = new Map();

for (const book of books) {
if (!result.has(book.category)) {
result.set(book.category, []);
}

result.get(book.category).push(book.title);
}

return result;
}

/**
Expand All @@ -108,7 +157,9 @@ function groupByCategory(books) {
* intersection([1, 2, 3], [2, 3, 4]) // → [2, 3]
*/
function intersection(arrA, arrB) {
// 여기를 작성하세요
const setB = new Set(arrB);

return [...new Set(arrA.filter((item) => setB.has(item)))];
}

/**
Expand All @@ -119,7 +170,7 @@ function intersection(arrA, arrB) {
* unique([1, 2, 2, 3]) // → [1, 2, 3]
*/
function unique(arr) {
// 여기를 작성하세요
return [...new Set(arr)];
}

// ─────────────────────────────────────────────
Expand All @@ -134,7 +185,9 @@ function unique(arr) {
* getOutOfStock({ 어린왕자: 3, "1984": 0 }) // → ["1984"]
*/
function getOutOfStock(stock) {
// 여기를 작성하세요
return Object.entries(stock)
.filter(([title, quantity]) => quantity === 0)
.map(([title, quantity]) => title);
}

/**
Expand All @@ -145,7 +198,7 @@ function getOutOfStock(stock) {
* getTotalStock({ 어린왕자: 3, "1984": 0, 해리포터: 2 }) // → 5
*/
function getTotalStock(stock) {
// 여기를 작성하세요
return Object.values(stock).reduce((sum, quantity) => sum + quantity, 0);
}

/**
Expand All @@ -156,7 +209,11 @@ function getTotalStock(stock) {
* removeNullish({ title: "어린왕자", author: null }) // → { title: "어린왕자" }
*/
function removeNullish(obj) {
// 여기를 작성하세요
return Object.fromEntries(
Object.entries(obj).filter(
([key, value]) => value !== null && value !== undefined,
),
);
}

// ─────────────────────────────────────────────
Expand All @@ -174,7 +231,28 @@ function removeNullish(obj) {
* getAvgPriceByCategory(books) // → { 소설: 15000, 교육: 26000 }
*/
function getAvgPriceByCategory(books) {
// 여기를 작성하세요
const grouped = books.reduce((acc, book) => {
const { category, price } = book;

if (!acc[category]) {
acc[category] = {
sum: 0,
count: 0,
};
}

acc[category].sum += price;
acc[category].count += 1;

return acc;
}, {});

return Object.fromEntries(
Object.entries(grouped).map(([category, info]) => [
category,
info.sum / info.count,
]),
);
}

/**
Expand All @@ -187,7 +265,11 @@ function getAvgPriceByCategory(books) {
* sortBy(books, "title") // → 제목 가나다순 새 배열
*/
function sortBy(books, key) {
// 여기를 작성하세요
return [...books].sort((a, b) => {
if (a[key] > b[key]) return 1;
if (a[key] < b[key]) return -1;
return 0;
});
}

/**
Expand All @@ -202,7 +284,12 @@ function sortBy(books, key) {
* // → [{ title: "어린왕자", price: 12000, category: "소설" }]
*/
function flattenCategories(categories) {
// 여기를 작성하세요
return categories.flatMap((categoryGroup) =>
categoryGroup.books.map((book) => ({
...book,
category: categoryGroup.category,
})),
);
}

// ─────────────────────────────────────────────
Expand All @@ -222,8 +309,10 @@ function flattenCategories(categories) {
*
* for (const book of createBookIterator(books)) { ... }
*/
function createBookIterator(books) {
// 여기를 작성하세요
function* createBookIterator(books) {
for (const book of books) {
yield book;
}
}

/**
Expand All @@ -236,7 +325,20 @@ function createBookIterator(books) {
* paginate(books, 1, 2) // → { data: [books[0], books[1]], totalPages: 3, currentPage: 1 }
*/
function paginate(books, page, size) {
// 여기를 작성하세요
const totalPages = Math.ceil(books.length / size);

if (page < 1 || page > totalPages) {
throw new Error('유효하지 않은 페이지 번호입니다.');
}

const start = (page - 1) * size;
const end = start + size;

return {
data: books.slice(start, end),
totalPages,
currentPage: page,
};
}

// ─────────────────────────────────────────────
Expand Down
30 changes: 0 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.