문제

Given two arrays arr1 and arr2, return a new array joinedArray. All the objects in each of the two inputs arrays will contain an id field that has an integer value. 

joinedArray is an array formed by merging arr1 and arr2 based on their id key. The length of joinedArray should be the length of unique values of id. The returned array should be sorted in ascending order based on the id key.

If a given id exists in one array but not the other, the single object with that id should be included in the result array without modification.

If two objects share an id, their properties should be merged into a single object:

  • If a key only exists in one object, that single key-value pair should be included in the object.
  • If a key is included in both objects, the value in the object from arr2 should override the value from arr1.

https://leetcode.com/problems/join-two-arrays-by-id/

 

예시

코드

/**
 * @param {Array} arr1
 * @param {Array} arr2
 * @return {Array}
 */
var join = function(arr1, arr2) {
    const hashMap = {};
    
    for(obj of arr1.concat(arr2)){
        const id = obj["id"];
        
        if(hashMap[id]){
            // id exist
            hashMap[id] = {...hashMap[id], ...obj};
            
        }else{
            hashMap[id] = obj;
        }
        
    }
    
    
    return Object.values(hashMap);
};

hashMap이라는 새로운 객체를 만들고, id를 key로 갖고 객체를 value로 갖도록 hashMap 형태로 만들었다. hashMap에 해당 id가 없는 경우에는 hashMap에 새로 추가했다. 이미 key가 id인 객체가 있는 경우에는 스프레드 연산자를 활용해서 기존에 있던 객체와 새로운 객체를 합쳐서 같은 key인 경우에는 뒤에 있는 객체의 value로 덮어씌울 수 있도록 했다.

문제에서 정렬을 하라고 했는데, JS는 object를 key 값 기준으로 정렬해주기 때문에 따로 정렬해주지 않았다.

그 후 `Object.values()` 를 활용해 values로 이루어진 배열 형태를 반환한다.

728x90

문제

Given an object or an array, return if it is empty.

  • An empty object contains no key-value pairs.
  • An empty array contains no elements.

You may assume the object or array is the output of JSON.parse.

https://leetcode.com/problems/is-object-empty/

 

예시

 

코드

/**
 * @param {Object|Array} obj
 * @return {boolean}
 */
var isEmpty = function(obj) {
    return JSON.stringify(obj).length == 2;
};

인자로 들어오는 obj의 형식이 Object이거나 Array이기 때문에 이를 JSON.stringify를 이용해 JSON 문자열로 변환하였다. 그렇다면 비어있는 array의 경우 `'[]'` 로 변환이 되고, 비어있는 Object의 경우 `'{}'`로 변환이 되기 때문에 비어있을 경우 length가 2가 된다. 따라서 길이가 2인지 여부를 판단하여 리턴해주었다.

728x90

문제

Given a function fn, an array of arguments args, and an interval time t, return a cancel function cancelFn.

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

setTimeout(cancelFn, cancelTimeMs)

The function fn should be called with args immediately and then called again every t milliseconds until cancelFn is called at cancelTimeMs ms.

https://leetcode.com/problems/interval-cancellation/

 

예시

 

코드

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    fn(...args);
    const timerId = setInterval(() => {fn(...args)}, t);
    
    return function(){
       clearInterval(timerId);
    }
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 2;
 *  const args = [4], t = 35, cancelTimeMs = 190;
 *
 *  const start = performance.now();
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start);
 *      result.push({"time": diff, "returned": fn(...argsArr)});
 *  }
 *       
 *  const cancel = cancellable(log, args, t);
 *
 *  setTimeout(cancel, cancelTimeMs);
 *   
 *  setTimeout(() => {
 *      console.log(result); // [
 *                           //     {"time":0,"returned":8},
 *                           //     {"time":35,"returned":8},
 *                           //     {"time":70,"returned":8},
 *                           //     {"time":105,"returned":8},
 *                           //     {"time":140,"returned":8},
 *                           //     {"time":175,"returned":8}
 *                           // ]
 *  }, cancelTimeMs + t + 15)    
 */

cancellable 함수는 function을 리턴해야 하며, 호출하였을 때 특정 함수의 호출을 cancel 하는 역할을 한다. log 함수는 계속 t(ms) 마다 실행이 되어야 하고, cancelTimeMs(ms) 후에 cancel 이 호출되고, 그때 log 함수가 멈춰야 한다. 따라서 cancellable 함수 내부에서 setInterval 을 이용해서 t(ms) 마다 fn을 호출하였고, 원하는 output에서 0초부터 로그가 찍히는 것을 원했기 때문에 setInterval 호출 전 따로 fn을 호출해주었다. 그리고 setInterval에서 반환된 timerId를 이용해서 interval을 취소시키는 행동을 하는 함수를 리턴한다.

728x90

문제

Given an array arr and a function fn, return a sorted array sortedArr. You can assume fn only returns numbers and those numbers determine the sort order of sortedArr. sortedArray must be sorted in ascending order by fn output.

You may assume that fn will never duplicate numbers for a given array.

https://leetcode.com/problems/sort-by/

 

예시

arr을 fn의 기준에 따라 정렬시킨다.

 

코드

/**
 * @param {Array} arr
 * @param {Function} fn
 * @return {Array}
 */
var sortBy = function(arr, fn) {
    return arr.sort((a, b)=>fn(a)-fn(b));
};

각각 a와 b를 fn 함수를 통과시킨 뒤, 오름차순으로 정렬하였다.

728x90

문제

Create a class ArrayWrapper that accepts an array of integers in its constructor. This class should have two features:

  • When two instances of this class are added together with the + operator, the resulting value is the sum of all the elements in both arrays.
  • When the String() function is called on the instance, it will return a comma separated string surrounded by brackets. For example, [1,2,3].

https://leetcode.com/problems/array-wrapper/

 

예시

 

코드

/**
 * @param {number[]} nums
 * @return {void}
 */
var ArrayWrapper = function(nums) {
    this.nums = nums;
    this.sum = nums.reduce((acc, cur)=> acc + cur, 0);
};

/**
 * @return {number}
 */
ArrayWrapper.prototype.valueOf = function() {
    return this.sum;
}

/**
 * @return {string}
 */
ArrayWrapper.prototype.toString = function() {
    return "[" + String(this.nums) + "]";
}

/**
 * const obj1 = new ArrayWrapper([1,2]);
 * const obj2 = new ArrayWrapper([3,4]);
 * obj1 + obj2; // 10
 * String(obj1); // "[1,2]"
 * String(obj2); // "[3,4]"
 */

ArrayWrapper라는 객체를 만들고, ArrayWrapper 끼리 덧셈을 했을 때와 String으로 표현했을 때 원하는 값이 나오도록 ` ArrayWrapper.prototype.valueOf()` 메소드와 `ArrayWrapper.prototype.toString()` 메소드를 재정의했다.

ArrayWrapper 객체끼리 덧셈을 했을 때, 전체 원소의 합이 리턴되어야 한다. 따라서 각 객체를 호출했을 때의 원시 값이 해당 객체의 원소들의 합을 리턴할 수 있도록 처음 ArrayWrapper 객체를 생성할 때 sum이라는 변수에 입력 받은 초기 배열의 합을 reduce를 이용하여 계산하고 저장해놓았다. valueOf() 안에서 합을 계산할 지 고민했으나, 호출할 때마다 합을 계산하는 것이 비효율적일 것 같아서 ArrayWrapper 객체 생성 시 계산하여 저장하도록 하였다.


* Object.prototype.valueOf

`객체.valueOf()`

객체의 원시 값을 반환한다.

- Object는 모두 valueOf를 상속받는다.

- 객체가 원시 값을 갖고 있지 않다면, valueOf는 객체를 반환하며, 사용자 정의 객체를 만들 때는 valueOf를 재정의할 수 있다.

- 보통 원시 값을 필요로 할 때 알아서 호출된다.

function MyNumberType(n) {
  this.number = n;
}

MyNumberType.prototype.valueOf = function () {
  return this.number;
};

const object1 = new MyNumberType(4);

console.log(object1 + 3); // 7

 

 

* Object.prototype.toString

`객체.toString()` `String(객체)`

객체를 나타낼 수 있는 String 값을 리턴한다.

- 객체가 텍스트 값으로 표시되거나 문자열이 예상되는 방식으로 참조될 때 자동으로 호출된다.

- Object에서 비롯된 모든 객체에 상속된다.

function Dog(name) {
  this.name = name;
}

const dog1 = new Dog('Jindo');
console.log(dog1.toString()); // [object Object] -> 재정의 안 됐을 때

Dog.prototype.toString = function () {
	return this.name;
}

const dog2 = new Dog('bbibbi');
console.log(dog2.toString()); // 'bbibbi'
728x90

문제

Given an array arr and a chunk size size, return a chunked array. A chunked array contains the original elements in arr, but consists of subarrays each of length size. The length of the last subarray may be less than size if arr.length is not evenly divisible by size.

You may assume the array is the output of JSON.parse. In other words, it is valid JSON.

Please solve it without using lodash's _.chunk function.

https://leetcode.com/problems/chunk-array/

 

예시

 

코드

/**
 * @param {Array} arr
 * @param {number} size
 * @return {Array}
 */
var chunk = function(arr, size) {
    const outputArr = [];
    
    for(let i = 0; i < arr.length; i+=size){
        outputArr.push(arr.slice(i, i+size));
    }
    
    return outputArr;
};

 

 

인자로 들어오는 arr과 size로 새로운 배열을 만들어 리턴해야 한다. arr에 있는 원소들을 size만큼 잘라서 새로운 배열에 넣어주면 된다. Array.prototype.slice()를 이용해서 인자로 들어오는 arr를 size 만큼 잘라주었다.

728x90

문제

Write a function createHelloWorld. It should return a new function that always returns "Hello World".

https://leetcode.com/problems/create-hello-world-function/

 

예시

 

코드

/**
 * @return {Function}
 */
var createHelloWorld = function() {
    
    return function(...args) {
        return "Hello World";
    }
};

/**
 * const f = createHelloWorld();
 * f(); // "Hello World"
 */

 

createHelloworld는 함수를 반환해야 하고, 반환된 함수를 호출했을 때 "Hello World"라는 문자열이 리턴되면 된다.

728x90

문제

Given a function fn, return a new function that is identical to the original function except that it ensures fn is called at most once.

  • The first time the returned function is called, it should return the same result as fn.
  • Every subsequent time it is called, it should return undefined.

https://leetcode.com/problems/allow-one-function-call/

 

예시

 

코드

type JSONValue = null | boolean | number | string | JSONValue[] | { [key: string]: JSONValue };
type OnceFn = (...args: JSONValue[]) => JSONValue | undefined

function once(fn: Function): OnceFn {
    let isCalled = false;

    return function (...args) {
        if(isCalled) return undefined;
        isCalled = true;
        
        return fn(...args);
    };
    
    
}

/**
 * let fn = (a,b,c) => (a + b + c)
 * let onceFn = once(fn)
 *
 * onceFn(1,2,3); // 6
 * onceFn(2,3,6); // returns undefined without calling fn
 */

once 함수는 단 한번만 실행되어야 하는 함수이다. 처음 실행됐을 때는 인자로 들어오는 fn이 실행되어야 하고, 그 후로 인자로 fn이 들어오면 undefined가 실행되어야 한다. 따라서 isCalled라는 변수를 이용해 fn의 실행 여부를 저장하고, 한 번 실행이 되면 isCalled를 true로 변경시켰다.

728x90

문제

Write a function createCounter. It should accept an initial integer init. It should return an object with three functions.

The three functions are:

  • increment() increases the current value by 1 and then returns it.
  • decrement() reduces the current value by 1 and then returns it.
  • reset() sets the current value to init and then returns it.

https://leetcode.com/problems/counter-ii/

 

예시

 

코드

/**
 * @param {integer} init
 * @return { increment: Function, decrement: Function, reset: Function }
 */
var createCounter = function(init) {
    let value = init;
    
    const counter = {
        increment() {
            return value += 1;
        },
        decrement(){
            return value -= 1;
        },
        reset(){
            return value = init;
        }
    }
    
    return counter;
};

/**
 * const counter = createCounter(5)
 * counter.increment(); // 6
 * counter.reset(); // 5
 * counter.decrement(); // 4
 */

 

 

createCounter가 counter 객체를 리턴하도록 하였다. counter 객체는 increment(), reset(), decrement() 메소드를 갖고 있으며, 인자로 들어온 초기값에 대해 각각 +1, init, -1 값을 리턴한다.

728x90

문제

Given an integer array arr and a mapping function fn, return a new array with a transformation applied to each element.

The returned array should be created such that returnedArray[i] = fn(arr[i], i).

Please solve it without the built-in Array.map method.

https://leetcode.com/problems/apply-transform-over-each-element-in-array/

 

예시

직접 map 함수를 구현하면 된다. arr에 있는 각 원소에 fn을 적용하여 다시 넣어주면 된다.

 

코드

/**
 * @param {number[]} arr
 * @param {Function} fn
 * @return {number[]}
 */
var map = function(arr, fn) {
    let newArr = [];
    
    arr.forEach((number, idx)=>{
        newArr.push(fn(number, idx));
    });
    
    return newArr;
};

리턴할 새로운 배열인 newArr를 만들고, arr를 돌면서 fn의 인자로 넣어준 뒤, 해당 결과를 newArr에 push 해주었다.

728x90

+ Recent posts