프론트엔드/Javascript 연습과제 해답

자바스크립트 문법 8 - 배열(Array)의 다양한 메서드 2 (변경과 정렬) 해답

syleemomo 2022. 1. 14. 14:56
728x90

 

* 연습과제 1

const userName = document.getElementById('user-name')
const userEmail = document.getElementById('user-email')
const userAge = document.getElementById('user-age')
const userList = document.getElementById('user-list')

const submitBtn = document.getElementById('user-add')
const users = []

function isValid(str){
    return str !== '' && str !== undefined
}
function buildElement(user){
    const userEl = document.createElement('div')
    userEl.className = 'user'
    userEl.innerHTML = `<div>name : ${user.name}</div>
                        <div>age : ${user.age}</div>
                        <div>email : ${user.email}</div>
                        `
    return userEl
}
function displayUsers(users){
    userList.innerHTML = ''
    users.forEach(user => {
        userList.appendChild(buildElement(user))
    })
}
function initInput(){
    userName.value = ''
    userEmail.value = ''
    userAge.value = ''
}

function addUser(){
    if(isValid(userName.value) && isValid(userEmail.value) && isValid(userAge.value)){
        users.push({ name: userName.value, email: userEmail.value, age: userAge.value})
        displayUsers(users)
        initInput()
    }else{
        alert("You missed some user information !")
    }

}

submitBtn.addEventListener('click', addUser)

 

* 연습과제 2

const companies = ['Samsung', 'LG', 'Google', 'Facebook', 'Amazon']
const companiesReversed = []

var popped = companies.pop()
while(popped !== undefined){
    companiesReversed.push(popped)
    popped = companies.pop()
}

console.log(companiesReversed)
const companies = ['Samsung', 'LG', 'Google', 'Facebook', 'Amazon']

const companiesReversed = companies
  .reduce((a, v) => [v, ...a], [])

console.log(companiesReversed)

reduce 함수와 스프레드연산자(...) 을 사용하면 훨씬 더 간단하게 처리할 수 있다. a 는 빈 배열로 시작해서 companies 배열의 배열요소를 reduce 로 하나씩 꺼낸 다음(v) 새로운 배열의 앞쪽에 추가한다. 

 

* 연습과제 3

const friends = [
    {name: 'victoria', age: 13, city: 'seoul'},
    {name: 'sun', age: 34, city: 'busan'},
    {name: 'johseb', age: 25, city: 'busan'},
    {name: 'syleemomo', age: 9, city: 'seoul'},
    {name: 'hannah', age: 41, city: 'daegu'},
    {name: 'shara', age: 37, city: 'seoul'},
    {name: 'martin', age: 28, city: 'daegu'},
    {name: 'gorgia', age: 39, city: 'seoul'},
    {name: 'nana', age: 24, city: 'busan'},
    {name: 'dannel', age: 19, city: 'seoul'},
]

const newFriends = [
    {name: 'Ami', aage: 27, city: 'ulsan'},
    {name: 'gracias', aage: 21, city: 'ulsan'},
]

friends.splice(2, 0, ...newFriends)
console.log(friends)

 

* 연습과제 4

const friends = [
    {name: 'victoria', age: 13, city: 'seoul'},
    {name: 'sun', age: 34, city: 'busan'},
    {name: 'johseb', age: 25, city: 'busan'},
    {name: 'syleemomo', age: 9, city: 'seoul'},
    {name: 'hannah', age: 41, city: 'daegu'},
    {name: 'shara', age: 37, city: 'seoul'},
    {name: 'martin', age: 28, city: 'daegu'},
    {name: 'gorgia', age: 39, city: 'seoul'},
    {name: 'nana', age: 24, city: 'busan'},
    {name: 'dannel', age: 19, city: 'seoul'},
]

friends.splice(4, 2)
console.log(friends)

 

* 연습과제 5

const friends = [
  {name: 'victoria', age: 13, city: 'seoul'},
  {name: 'sun', age: 34, city: 'busan'},
  {name: 'johseb', age: 25, city: 'busan'},
  {name: 'syleemomo', age: 9, city: 'seoul'},
  {name: 'shara', age: 37, city: 'seoul'},
  {name: 'hannah', age: 41, city: 'daegu'},
  {name: 'martin', age: 28, city: 'daegu'},
  {name: 'gorgia', age: 39, city: 'seoul'},
  {name: 'nana', age: 24, city: 'busan'},
  {name: 'dannel', age: 19, city: 'seoul'},
]

for(let i=0; i<friends.length; i++){
  const friend = friends[i]
  if(friend.city === 'seoul'){
    friends.splice(i, 1)
    i--
  }
}
console.log(friends)

splice 메서드는 원본배열을 변경하기 때문에 배열요소를 제거하고 나서 다른 요소들이 왼쪽으로 쉬프트된다. 그러므로 forEach 를 사용하면 제대로 동작하지 않는다. splice 메서드로 제거한 다음에 일반적인 for 문을 사용하면 쉬프트되어도 인덱스 값을 1만큼 감소시켜서 해당 배열요소부터 순차적으로 조회가 가능한데 forEach 사용시 쉬프트되더라도 그대로 다음 인덱스값을 조회하기 때문에 중간에 요소를 건너띄고 검사하게 된다. 

const friends = [
    {name: 'victoria', age: 13, city: 'seoul'},
    {name: 'sun', age: 34, city: 'busan'},
    {name: 'johseb', age: 25, city: 'busan'},
    {name: 'syleemomo', age: 9, city: 'seoul'},
    {name: 'hannah', age: 41, city: 'daegu'},
    {name: 'shara', age: 37, city: 'seoul'},
    {name: 'martin', age: 28, city: 'daegu'},
    {name: 'gorgia', age: 39, city: 'seoul'},
    {name: 'nana', age: 24, city: 'busan'},
    {name: 'dannel', age: 19, city: 'seoul'},
]

const friendsFiltered = friends.filter( friend => friend.city !== 'seoul')
console.log(friendsFiltered)
const friends = [
  {name: 'victoria', age: 13, city: 'seoul'},
  {name: 'sun', age: 34, city: 'busan'},
  {name: 'johseb', age: 25, city: 'busan'},
  {name: 'syleemomo', age: 9, city: 'seoul'},
  {name: 'shara', age: 37, city: 'seoul'},
  {name: 'hannah', age: 41, city: 'daegu'},
  {name: 'martin', age: 28, city: 'daegu'},
  {name: 'gorgia', age: 39, city: 'seoul'},
  {name: 'nana', age: 24, city: 'busan'},
  {name: 'dannel', age: 19, city: 'seoul'},
]

let cnt = 0
friends.forEach(function(friend, index){
  console.log(index)
  if(friend.city === 'seoul'){

    friends.splice(index, 1)
    friends.unshift('a')
    cnt++
  }
})
console.log(friends.splice(cnt))

 

 

* 연습과제 6

const friends = [
    {name: 'victoria', age: 13, city: 'seoul'},
    {name: 'sun', age: 34, city: 'busan'},
    {name: 'johseb', age: 25, city: 'busan'},
    {name: 'syleemomo', age: 9, city: 'seoul'},
    {name: 'hannah', age: 41, city: 'daegu'},
    {name: 'shara', age: 37, city: 'seoul'},
    {name: 'martin', age: 28, city: 'daegu'},
    {name: 'gorgia', age: 39, city: 'seoul'},
    {name: 'nana', age: 24, city: 'busan'},
    {name: 'dannel', age: 19, city: 'seoul'},
]

const friendsFiltered = friends
.sort( (a, b) => a.age - b.age)
.filter( friend => friend.age < 30)

console.log(friendsFiltered)

 

* 연습과제 7

const friends = [
    {name: 'victoria', age: 13, city: 'seoul'},
    {name: 'sun', age: 34, city: 'busan'},
    {name: 'johseb', age: 25, city: 'busan'},
    {name: 'syleemomo', age: 9, city: 'seoul'},
    {name: 'hannah', age: 41, city: 'daegu'},
    {name: 'shara', age: 37, city: 'seoul'},
    {name: 'martin', age: 28, city: 'daegu'},
    {name: 'gorgia', age: 39, city: 'seoul'},
    {name: 'nana', age: 24, city: 'busan'},
    {name: 'dannel', age: 19, city: 'seoul'},
]

friends.sort( (a, b) => {
    const aName = a.name.toLowerCase()
    const bName= b.name.toLowerCase()
    if(aName > bName) return 1
    if(aName < bName) return -1
    return 0
})


console.log(friends)
const friends = [
  {name: 'victoria', age: 13, city: 'seoul'},
  {name: 'sun', age: 34, city: 'busan'},
  {name: 'johseb', age: 25, city: 'busan'},
  {name: 'syleemomo', age: 9, city: 'seoul'},
  {name: 'hannah', age: 41, city: 'daegu'},
  {name: 'shara', age: 37, city: 'seoul'},
  {name: 'martin', age: 28, city: 'daegu'},
  {name: 'gorgia', age: 39, city: 'seoul'},
  {name: 'nana', age: 24, city: 'busan'},
  {name: 'dannel', age: 19, city: 'seoul'},
]

friends.sort( (a, b) => a.name > b.name ? 1 : -1)


console.log(friends)

삼항연산자를 사용하면 좀 더 간단하다. 

 

* 연습과제 8

해답1

const movies = [
    {title: 'Harry Potter', release: '2003-02-22'}, 
    {title: 'Indiana Jhones', release: '2009-01-09'}, 
    {title: 'Terminator', release: '2007-04-11'},
    {title: 'Dracula', release: '2007-04-13'},
    {title: 'Jurassic Park', release: '2007-05-13'},
    {title: 'Iron man', release: '2012-12-18'},
    {title: 'Spider man', release: '2017-03-07'}
]

movies.sort( (a, b) => {
    const aRelease = a.release.split('-')
    const bRelease = b.release.split('-')
    const yearA = aRelease[0], monthA = aRelease[1], dayA = aRelease[2]
    const yearB = bRelease[0], monthB = bRelease[1], dayB = bRelease[2]

    // 년도 비교하기
    if(yearA < yearB) return 1 // b 가 크면 순서 변경하기
    if(yearA > yearB) return -1 // b 가 작으면 그대로 두기

    // 년도가 같으면 달 비교하기
    if(monthA < monthB) return 1 // b 가 크면 순서 변경하기
    if(monthA > monthB) return -1 // b 가 작으면 그대로 두기

    // 년도와 달이 모두 같으면 일 비교하기
    if(dayA < dayB) return 1 // b 가 크면 순서 변경하기
    if(dayA > dayB) return -1 // b 가 작으면 그대로 두기

    return 0
})


console.log(movies)

해답2

const movies = [
    { title: 'Harry Potter', release: '2003-02-22' },
    { title: 'Indiana Jhones', release: '2009-01-09' },
    { title: 'Terminator', release: '2007-04-11' },
    { title: 'Dracula', release: '2007-04-13' },
    { title: 'Jurassic Park', release: '2007-05-13' },
    { title: 'Iron man', release: '2012-12-18' },
    { title: 'Spider man', release: '2017-03-07' }
]

movies.sort((a, b) => {
    if (a.release < b.release) return 1
    if (a.release > b.release) return -1
    return 0
})

console.log(movies)

해답 3

const movies = [
  { title: 'Harry Potter', release: '2003-02-22' },
  { title: 'Indiana Jhones', release: '2009-01-09' },
  { title: 'Terminator', release: '2007-04-11' },
  { title: 'Dracula', release: '2007-04-13' },
  { title: 'Jurassic Park', release: '2007-05-13' },
  { title: 'Iron man', release: '2012-12-18' },
  { title: 'Spider man', release: '2017-03-07' }
]

movies.sort((a, b) => a.release < b.release ? 1 : -1)

console.log(movies)

문자열은 각 캐릭터를 잘라서 앞에서부터 하나씩 사전순으로 비교한다. 삼항연산자를 사용하면 더 간단한다. 

 

* 연습과제 9~10 통합 

const rootDiv = document.getElementById('root')
const priceBtn = document.getElementById('price-btn')
const searchInput = document.getElementById('search-input')
const API_URL = 'http://makeup-api.herokuapp.com/api/v1/products.json?brand=maybelline' 

let shouldSort = false
let shouldFilter = false 
let originalProducts = null
let keyword = ''


// 상품 정보로부터 엘레먼트 생성
function buildElement(product){
    const item = document.createElement('div') 
    item.className = 'product'

    item.innerHTML = `
                      <div class='product-img'><img src=${product.image_link} alt=${product.name}/></div>
                      <div class='product-name'>${product.name} ($${product.price})</div>
                      <div class='product-description'>${product.description}</div>
                      <div class='product-type'>${product.product_type}</div>
                  `
    return item
}

// 상품 배열을 이용하여 화면에 렌더링하기
function displayProducts(products){
    rootDiv.innerHTML = '' // 화면 초기화
    products.forEach(product => {
        rootDiv.appendChild(buildElement(product))
    })
}

function updateProducts(products, keyword){
    let newProducts = [...products] // 원본배열 복사하기
    if(shouldFilter){  // 조건 쿼리 (conditional query)
        newProducts = newProducts.filter(product => product.product_type.toLowerCase().includes(keyword.toLowerCase()))
    } 
    if(shouldSort){
        newProducts.sort( (p1, p2) => parseFloat(p1.price) - parseFloat(p2.price) ) 
    }
    return newProducts
}

// 상품유형 검색하기
function searchProducts(e){
    shouldFilter = e.target.value !== '' // 사용자 입력여부 검사하기
    keyword = e.target.value
    console.log(shouldFilter)

    const newProducts = updateProducts(originalProducts, keyword) // 검색 및 정렬하기
    displayProducts(newProducts) // 화면 업데이트

}

// 가격 낮은순으로 정렬하기
function sortByPrice(e){
    shouldSort = !shouldSort // 상태 토글하기
    console.log(shouldSort)

    const newProducts = updateProducts(originalProducts, keyword) // 검색 및 정렬하기
    displayProducts(newProducts) // 화면 업데이트 
}

// 서버에서 데이터 가져오기
fetch(API_URL)
.then(function(res){
    return res.json()
})
.then(function(products){
    originalProducts = products // 원본 데이터 저장
    displayProducts(products) // 초기 렌더링

    // 서버에서 데이터 가져오기가 완료되면 이벤트 연결하기 => 만약 then 메서드 밖에서 이벤트 연결하면 서버에서 데이터 가져오기도 전에 사용자가 클릭하거나 검색하므로 에러날 수도 있음
    priceBtn.addEventListener('click', sortByPrice)
    searchInput.addEventListener('input', searchProducts)
})

 

* 연습과제 11

const customers = [
  {name: '나봄', age: 22, city: '서울', state: '도봉구'},
  {name: '다은', age: 34, city: '부산', state: '해운대구'},
  {name: '가온', age: 28, city: '대구', state: '수성구'},
  {name: '보라', age: 25, city: '부산', state: '부산진구'},
  {name: '해련', age: 41, city: '대구', state: '달서구'},
  {name: '여름', age: 56, city: '서울', state: '중랑구'},
  {name: '재찬', age: 9, city: '서울', state: '마포구'},
  {name: '바다', age: 35, city: '부산', state: '해운대구'},
  {name: '초롱', age: 17, city: '대구', state: '달서구'},
  {name: '진솔', age: 37, city: '서울', state: '도봉구'},
  {name: '한울', age: 67, city: '부산', state: '부산진구'},
  {name: '승아', age: 34, city: '대구' , state: '수성구'},
  {name: '다빈', age: 42, city: '부산', state: '동래구'},
  {name: '잔디', age: 38, city: '대구', state: '북구'},
  {name: '새롬', age: 39, city: '서울', state: '마포구'},
  {name: '노을', age: 13, city: '서울', state: '구로구'},
  {name: '한결', age: 24, city: '부산', state: '동래구'},
  {name: '마루', age: 19, city: '서울', state: '마포구'},
]

function classifyByKey(arr, key){
  const result = {}
  arr.forEach(function(el){
    if(!result[el[key]]) result[el[key]] = []
    result[el[key]].push(el)
  })
  return result 
}

// console.log(classifyByKey(customers, 'city'))

const classifiedByCity = classifyByKey(customers, 'city')

for(let city in classifiedByCity){
  classifiedByCity[city] = classifyByKey(classifiedByCity[city], 'state')
}
console.log(classifiedByCity)

 

클로저와 재귀함수를 사용한 해답은 다음과 같다. 

const customers = [
  {name: '나봄', age: 22, city: '서울', state: '도봉구'},
  {name: '다은', age: 34, city: '부산', state: '해운대구'},
  {name: '가온', age: 28, city: '대구', state: '수성구'},
  {name: '보라', age: 25, city: '부산', state: '부산진구'},
  {name: '해련', age: 41, city: '대구', state: '달서구'},
  {name: '여름', age: 56, city: '서울', state: '중랑구'},
  {name: '재찬', age: 9, city: '서울', state: '마포구'},
  {name: '바다', age: 34, city: '부산', state: '해운대구'},
  {name: '초롱', age: 17, city: '대구', state: '달서구'},
  {name: '진솔', age: 37, city: '서울', state: '도봉구'},
  {name: '한울', age: 67, city: '부산', state: '부산진구'},
  {name: '승아', age: 34, city: '대구' , state: '수성구'},
  {name: '다빈', age: 42, city: '부산', state: '동래구'},
  {name: '잔디', age: 38, city: '대구', state: '북구'},
  {name: '새롬', age: 39, city: '서울', state: '마포구'},
  {name: '노을', age: 13, city: '서울', state: '구로구'},
  {name: '한결', age: 24, city: '부산', state: '동래구'},
  {name: '마루', age: 39, city: '서울', state: '마포구'},
]
const criterias = ['city', 'state', 'age']

function generateClassifyFunc(criterias){ 
  let depth = 0

  function classifyByKey(arr){
    const result = {}

    arr.forEach(function(user){  // 분류기준으로 분류
      const basis = user[criterias[depth]]
      if(!result[basis]) result[basis] = []
      result[basis].push(user)
    })

    if(depth === criterias.length-1){ // 분류기준 갯수만큼 분류
      return result 
    }else{
      depth++
      // console.log(result)

      for(let basis in result){  // 객체의 프로퍼티값(배열)을 재분류
        result[basis] = classifyByKey(result[basis])
      }
      return result
    }
  }
  return classifyByKey // depth, criterias 를 기억하는 클로저 
}

const classifyByKey = generateClassifyFunc(criterias)
console.log(classifyByKey(customers))

728x90