2021.1.28 / Immersive 1 HA 복기 (1/3)

Mono crom·2021년 1월 28일
0

첫 번째 HA가 아침 9시에 시작해서 하루를 꼬박 넘겨 밤 12시 30분 무렵에서야 마무리되었다.

누가 채찍으로 등을 찰싹찰싹 때리지 않으면 도무지 진득하게 집중하지 못하는 정신머리 반, 다 풀어봤던거 약간씩 난이도 올려서 낸건데도 처음이랑 똑같이 헤매는 모지리 두뇌 반으로 어기적 어기적 헤쳐나가다보니 이렇게 오래걸렸다. 세상에...

이머시브 들어와서 배운것들 이번주에 단디 붙들어매지 않으면 이 뒤가 굉장히 고달플 것 같다는 생각이 강하게 들어서 이번에 좀 빡세게 복기하면서 한 줄 한 줄 음미해보려고 한다. ㄱㄱ!


Destructing

  • obj 객체가 주어져있고, obj 객체를 이용해 변경된 객체를 만들어내는 gettingJob 함수가 존재합니다.
    변경된 객체는 모든 속성은 그대로 유지하되, company.nameUnemployed에서 google로 바뀌어야 합니다.
    이 때 반드시 구조 분해 할당(destructing)을 이용하십시오.
const obj = {
  name: 'Lee',
  company: {
    name: 'Unemployed', // <- 요거. 요걸 google 로 바꿔야 한다.
    skill: ['Development', 'Writing'],
    role: {
      name: 'Software Engineer'
    }
  },
  age: 35
}

const gettingJob = () => {
  return { 코드 짜넣는 곳 }

1. 뭐가 문제였나?

{...obj} 하면 obj 객체의 내용이 똑같이 전개된다는 건 알고 있었다. 문제는 어떻게 obj의 일부 내용을 바꾸면서 전개시킬 수 있는지를 알 수 없었다. 구글링 시작.

2. 뭘 알아냈나?

const obj = { name: "ggami", specis: "puppy" };

const change = { ... obj, specis: "dog" };

console.log(change) // { name: "ggami", specis: "dog" }

일단 obj를 전개시켜놓고 콤마를 찍은 뒤, 그 뒤에 전개된 내용 중 변경하고 싶은 내용을 적으면 된다는 사실을 알게 되었다. 전개시켜놓고, 변경한다. 반대순서는 안된다. 이제 이걸 응용쳐서 본 문제를 풀면 되겠다 싶었다.

3. 어떻게 풀어냈나?

const gettingJob = () => {
  return { ...obj, company: { ...obj.company, name: 'google' } }
}

먼저 { ...obj } 로 obj의 내용을 전개시켜놓고, { ...obj, company: { } } 요런 식으로 obj의 내용 중 company 프로퍼티의 내용을 변경할 것임을 알린다. 그럼 company의 value 인 객체 내부에 있는 name프로퍼티를 어떻게 변경할 수 있을까? company 객체의 내부로 한 걸음 들어가서 살펴보면, 아래와 같이 할 수 있다.

위에서 ggami 의 specis를 puppy에서 dog 로 바꾼 것과 같은 원리로, { ...obj.company, name: "google" } 이렇게 하면 company 객체의 name 값을 바꿀 수 있다. 이제 한 걸음 뒤로 빠져서 바라보면 전체 코드는 위에 작성해놓은 결과물과 같은 모습이 되어있을 것이다.




Queue

  • 자료구조 중 Queue 클래스를 구현하세요.
    storage를 배열이 아닌 객체로 구현하세요.
    Queue는 더 이상 필요하지 않은 값을 보관하지 않습니다.
    추가 및 삭제는 O(1) 시간 복잡도로 구현되어야 합니다.
const Queue = function () {
  this._storage = {}
};

Queue.prototype.add = function () {};

Queue.prototype.remove = function() {};

1. 뭐가 문제였나?

add까지는 알겠는데 remove 메소드를 O(1)의 시간 복잡도로 구현하는 방법을 모르겠다. O(1) 이 되려면 탐색과정 없이 객체 맨 앞에 있는 프로퍼티를 탁 잡아 없애야 하는데, 배열에서야 인덱스가 있으니까 쉽지만 객체에서 어찌해야 할꼬? 또 고민과 구글링 시작.

2. 뭘 알아냈나?

객체의 맨 앞 프로퍼티를 자동으로 탐지해서 삭제해주는 메소드는 존재하지 않는 것 같다. 그럼 어떡해?
객체를 배열화 해야한다는 결론을 냈다. 즉, 수동으로 인덱스를 만들어야 한다.

item 을 queue에 추가하려고 한다면, { index: item } 형식으로 인덱스를 키로 가진채로 저장되게끔 해야 한다. 그래야 나중에 remove 하려고 할 때 맨 앞놈이 누군지 탐색하지 않아도 잡아낼 수 있다.

그럼 이제 remove 메소드를 사용하면 delete this._storage(0) 를 하면 된다고 넘어가고, 그 다음 작업이 고민이다. 맨 앞 프로퍼티가 삭제된다고 해도 그 뒤에 있던 프로퍼티들이 키값으로 담긴 index는 바뀌지 않기 때문이다. 문제 해결을 위한 힌트는 어느정도 얻었으니 나머지는 코드를 짜면서 고민해보기로 한다.

3. 어떻게 풀어냈나?

const Queue = function () {
  this._storage = {}
  this.firstIndex = 0
  this.length = 0
};

Queue 생성자에 firstIndex 프로퍼티를 추가해서 this._storage[this.firstIndex] 하면 곧바로 맨 앞 프로퍼티를 가리킬 수 있도록 했다. fitstIndex 를 1씩 증가시키면 remove 메소드가 호출될 때마다 맨 앞 프로퍼티가 지목될 수 있다.

Queue.prototype.add = function (item) {
  this._storage[this.length + this.firstIndex] = item
  this.length++
};

최초에 this.length + this.firstIndex는 0이고, 그 다음은 1, 그 다음은 2 이런 식으로 인덱스 역할을 하는 key가 만들어지고, 그 value 로 item 이 저장된다. 그리고 firstIndex 는 0으로 고정되어 있지. 왜 굳이 length 에 firstIndex 를 더해줬는지는 아래 remove 메소드를 보면서 이야기한다.

Queue.prototype.remove = function() {
  // storage 가 비었으면 삭제할게 없으므로 undefined 반환
  if (this.length <= 0) {
    return undefined
  }

  // 맨 앞 프로퍼티 제거
  let removeItem = this._storage[this.firstIndex]
  delete this._storage[this.firstIndex]

  // 첫 번째 인덱스, 객체의 길이 재조정
  this.firstIndex++
  this.length--

  return removeItem;
};

맨 앞 프로퍼티가 삭제되었으므로 this.length 는 1 줄어야 하고, 이제 맨 앞 프로퍼티의 key 는 0 이 아닌 1 이므로 this.firstIndex 는 1 증가해야 한다. 그러면 this.length + this.firstIndex 값은 변한게 없으므로 add 메소드에서 인덱스 역할을 하는 key도 여전히 제대로 동작한다. 깔끔!

profile
니가 진짜로 원하는게 뭐야

0개의 댓글