문제

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

문제

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

문제

Given an array of functions [f1, f2, f3, ..., fn], return a new function fn that is the function composition of the array of functions.

The function composition of [f(x), g(x), h(x)] is fn(x) = f(g(h(x))).

The function composition of an empty list of functions is the identity function f(x) = x.

You may assume each function in the array accepts one integer as input and returns one integer as output.

https://leetcode.com/problems/function-composition/

 

예시

functions에 있는 각 함수들을 뒤에서부터 실행하면 된다. 주어진 x 값을 이용하여 x의 값을 업데이트한다.

 

코드

/**
 * @param {Function[]} functions
 * @return {Function}
 */

Array.prototype.myReverse = function(){
    return this.map((item,idx) => this[this.length-1-idx]);
}

var compose = function(functions) {
    
    return function(x) {
        let value = x;
        
        functions.myReverse().forEach((fn)=>{
            value = fn(value);
        });
        
        return value;
    }
};

/**
 * const fn = compose([x => x + 1, x => 2 * x])
 * fn(4) // 9
 */

 

함수 배열의 순서를 바꾼 뒤, 바뀐 함수 배열을 돌면서 value 값을 업데이트 했다.

Array.prototype.reverse()가 존재하지만, 직접 구현해보고 싶었다. (추가적으로, reverse()가 좀 느리지 않을까라는 생각이 들었다. 관련해서는 참고 링크를 보면 좋을 것 같다.)

 

 

참고 링크

https://medium.com/@toaonly42/array-prototype-reverse-%EA%B0%80-%EC%B5%9C%EC%84%A0%EC%9D%B8%EA%B0%80-5acb17e315d3

 

Array.prototype.reverse 가 최선인가?

🤔 뜬금없는 의문,

medium.com

https://gurtn.tistory.com/121

 

[JS] 반복문 (for, forEach 등) 속도 비교

JavaScript의 반복문으로 for loop 문, forEach 메서드, map 메서드, reduce 메서드, $.each (Jquery) 등 정말 많은 종류의 반복문이 존재합니다. 비교 해볼 반복문 for loop forEach map reduce $.each 속도 비교에 사용할

gurtn.tistory.com

 

728x90

문제

Given an integer array nums, a reducer function fn, and an initial value init, return the final result obtained by executing the fn function on each element of the array, sequentially, passing in the return value from the calculation on the preceding element.

This result is achieved through the following operations: val = fn(init, nums[0]), val = fn(val, nums[1]), val = fn(val, nums[2]), ... until every element in the array has been processed. The ultimate value of val is then returned.

If the length of the array is 0, the function should return init.

Please solve it without using the built-in Array.reduce method.

https://leetcode.com/problems/array-reduce-transformation/

 

예시

input으로 nums 배열과 reduce로 실행할 함수, 그리고 초기 값을 받는다. accum은 fn에서 리턴한 값이 들어가고, curr은 nums 배열에 있는 숫자가 들어간다.

 

코드

/**
 * @param {number[]} nums
 * @param {Function} fn
 * @param {number} init
 * @return {number}
 */
var reduce = function(nums, fn, init) {
    if(nums.length === 0) return init;
    
    let accum = init;
    nums.forEach((num)=>{
        accum = fn(accum, num);
    });
    
    return accum;
};

문제에 적혀있는 대로, nums 배열의 길이가 0이면 초기 값을 리턴한다.

fn(accum, curr)에서 accum은 앞선 실행됐던 fn의 결과 값이고, curr은 현재 nums 배열에 있는 숫자이다. for문을 돌면서 nums에서 각 숫자가 fn의 curr로 들어갈 수 있도록 하였고, fn의 결과를 accum 변수에 저장해주었다.

728x90

문제

Given a positive integer millis, write an asynchronous function that sleeps for millis milliseconds. It can resolve any value.

https://leetcode.com/problems/array-prototype-last/

 

예시

0.1초 후 then 안에 있는 함수가 실행된다.

 

코드

/**
 * @param {number} millis
 * @return {Promise}
 */
async function sleep(millis) {
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            resolve();
        }, millis);
    });
}

/** 
 * let t = Date.now()
 * sleep(100).then(() => console.log(Date.now() - t)) // 100
 */

sleep 함수가 Promise 객체를 반환하도록 하였다. sleep 함수의 인자로 들어온 millis 만큼 지연시킨 후, then에 있는 함수를 실행해야 하기 때문에 setTimeout을 이용하였다. millis 만큼의 시간이 흐르면 일이 성공적으로 끝났음을 알리는 resolve() 함수를 호출한다. 요구사항에서 value를 넘기는 것은 필요하지 않아서 resolve 함수의 인자로 아무 것도 넣어주지 않았다.

728x90

문제

Write code that enhances all arrays such that you can call the array.last() method on any array and it will return the last element. If there are no elements in the array, it should return -1.

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

https://leetcode.com/problems/array-prototype-last/

 

예시

배열의 마지막 원소인 3 이 출력된다.

 

배열이 비어있기 때문에 -1이 출력된다.

 

코드

/**
 * @return {null|boolean|number|string|Array|Object}
 */
Array.prototype.last = function () {
    if (this.length === 0) return -1;

    return this[this.length - 1];
};

/**
 * const arr = [1, 2, 3];
 * arr.last(); // 3
 */

배열이 비어있을 때는 -1을 리턴하고, 나머지 경우에는 배열의 마지막 원소를 리턴하면 되기 때문에 length가 0인 지를 먼저 확인한다. 0일 때 -1을 리턴하도록 하고, 그 외의 경우에는 배열의 마지막 원소를 리턴한다.

728x90

문제

Given an integer n, return a counter function. This counter function initially returns n and then returns 1 more than the previous value every subsequent time it is called (n, n + 1, n + 2, etc).

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

 

예시

n이 10일 때, 처음 counter() 메소드를 호출하면 10이 나오고, 또 counter() 메소드를 호출하면 11이 나오고, 또 counter() 메소드를 호출하면 12가 출력된다. 

 

n이 -2일 때 counter()를 5번 호출하면 -2, -1, 0, 1, 2가 출력된다.

 

코드

function createCounter(n: number): () => number {
    return function() {
        return n++;
    }
}


/** 
 * const counter = createCounter(10)
 * counter() // 10
 * counter() // 11
 * counter() // 12
 */

createCounter의 인수로 n이 들어오고, createCounter는 함수를 리턴한다. 리턴된 함수가 counter 변수에 담긴다.

counter 함수가 호출될 때마다 n을 증가시켜야 하므로, n을 증가시키는 코드가 필요하다. 처음 호출될 때는 n이 출력되어야 하므로, n++로 후위 증감 연산자를 이용한다.

728x90

+ Recent posts