【问题标题】:Memoizing Objects With Same Keys, But Different Order用相同的键记忆对象,但顺序不同
【发布时间】:2021-10-26 15:39:39
【问题描述】:

前几天我接受了一次面试,被要求编写我自己的 memoize 函数,它接受一个函数,并返回它的包装版本。我以前使用过利用记忆的函数,但从未花时间研究它们在内部是如何工作的。不用说,我没有得到这份工作,哈哈。

一个有趣的要求是,对于 object 类型的参数,如果键相同但顺序不同,函数应该将它们视为相同的参数:

例如:

const one = {
   a: 1,
   b: 2,
   c: 3
}

const two = {
  c: 3,
  a: 1,
  b: 2
}

将被视为相同的参数。这是我的 memoize 函数,它的实现:

const memoize = fn => {
  const cache = {};

  return (...args) => {
    const key = JSON.stringify(args);

    if (!cache.hasOwnProperty(key)) {
      cache[key] = fn(...args);
    }

    return cache[key];
  };
}

const stringifyObj = (obj) => {
   console.log(obj)
   return JSON.stringify(obj)
}

const myMemo = memoize(stringifyObj)

const a = myMemo({ hello: "world", goodnight: "moon" })
const b = myMemo({ goodnight: "moon", hello: "world" })

执行 myMemo 两次最终会导致两个对象都被记录到控制台。但是,如果 memoize 函数设置为正确处理具有不同顺序的相同键的对象,我希望 console.log 只执行一次,打印 { hello: "world", goodnight: "moon" }

在这个例子中,我只使用一个对象作为参数,但实际上 memoize 函数应该支持 n 数量的所有不同类型的参数。如果有人可以解释如何处理任何数量的论点的问题,那就太棒了,但这不是必需的。为一个对象参数发布一个解决相同键、不同顺序问题的解决方案也很酷。

【问题讨论】:

  • 按关键顺序对参数对象的属性进行排序。这样,具有相同属性的对象也将具有相同的属性定位。
  • 这是个好主意。根据这个建议,我可以循环遍历 args 数组,并对找到的每个对象进行排序。不知道如果 JS 允许我改变 args 数组,我会检查的。否则我将创建一个新数组并在那里进行操作。

标签: javascript caching memoization


【解决方案1】:

我使用了 Robert 的建议,即按键对对象进行排序。我的实现似乎适用于任何类型的多个参数,包括多个对象。我不认为检查一个 arg 是否是一个对象是防弹的,但它足够好。

const memoize = (fn) => {
  const cache = {};

  return (...args) => {
    let i = 0;

    for (const arg of args) {
      if (
        typeof arg === "object" &&
        arg.constructor === Object &&
        arg !== null
      ) {
        const sortObject = (o) =>
          Object.keys(o)
          .sort()
          .reduce(
            (acc, key) => ({
              ...acc,
              [key]: o[key],
            }), {}
          );
        args[i] = sortObject(arg);
      }
      i++;
    }

    const key = JSON.stringify(args);

    if (!cache.hasOwnProperty(key)) {
      cache[key] = fn(...args);
    }

    return cache[key];
  };
};

将其放入文本编辑器并对其进行测试应该会产生以下结果:

function x(str, obj, num, obj) {
  console.log("hola");
}

const myMemo = memoize(x);
myMemo("hey", { a: 1, b: 2, c: 3 }, 24, { b: 2, c: 3, a: 1 }); // log
myMemo("bye", { a: 1, b: 2, c: 3 }, 24, { b: 2, c: 3, a: 1 }); // log
myMemo("hey", { a: 1, b: 2, c: 3 }, 24, { b: 2, c: 3, a: 1 }); // no log
myMemo("hey", { a: 1, b: 2, c: 3 }, 24, { b: 2, c: 3, a: 1 }); // no log
myMemo("bye", { a: 1, b: 2, z: 3 }, 24, { b: 2, z: 3, a: 1 }); // log
myMemo("bye", { a: 1, b: 2, z: 3 }, 24, { b: 2, z: 3, a: 1 }); // no log

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-16
    • 2019-09-29
    • 2014-05-09
    • 2013-08-25
    • 2020-01-23
    相关资源
    最近更新 更多