【Daily Interview】 - 01 实现一个简单的仓储系统

315 阅读3分钟

!! 说在前面的:本题目来源于京城一灯,已经过对方同意方分享记录

先来看看题目吧:

分析

题目看起来比较模糊,其实核心就是实现 object 的扁平化,这样就能够很好的比较 in 和 out 的数据,从而判断是否爆仓了。

怎么实现 object 的扁平化呢?

了解过深克隆的读者应该立马就会想到思路:递归。

如果我们的扁平化函数叫 _flatCargo,那么它应该怎么做呢?

  1. 声明一个 _store,用于存储被扁平化之后的数据
  2. 遍历 object,设当前被遍历的值叫做 n,首先确定 n 的 key
  3. 如果 n 是第一层,则它的 key 就是被遍历的 objec 的 key,否则需要加上上一层的 key
  4. 如果 n 是一个 object,则递归,参数是它自己以及当前的 key,否则将 n 存入 _store

思路如上,我们可以按部就班的实现 _flatCargo

const _flatCargo = (cargo = {}) => {
  const _store = {};
  const baseFlat = (cargo, baseKey) => {
    Object.keys(cargo).forEach(key => {
      const _cargo = cargo[key];
      const _key = baseKey ? `${baseKey}.${key}` : key;
      if (typeof _cargo === "object") {
        baseFlat(_cargo, key);
      } else {
        _store[_key] = _cargo;
      }
    });
  };
  return baseFlat(cargo);
}

现在来看看结果:

实现了对 object 的扁平化,货物的转入和转出就很轻松了:

  • transferIn:
    1. 将传入的参数扁平化,遍历扁平化后的货物对象,设当前被遍历的值叫做 c
    2. 将 c 存入 store 中:如果 store 中已经存在这个值,则数值加上 c,否则直接存入即可
  • transferOut
    1. 将传入的参数扁平化,遍历扁平化后的货物对象,设当前被遍历的值叫做 c
    2. 设定爆仓条件:store 没有这个货物,或者将要转出的货物数量大于 store 中对应货物的数量
    3. 如果没爆仓,则将货物转出,否则抛出爆仓的货物

接下来看看代码:

const store = {};
const transferIn = (cargo = {}) => {
  const _cargo = _flatCargo(cargo);
  Object.keys(_cargo).forEach(key => {
    const __cargo = _cargo[key];
    store[key] = store[key] ? store[key] + __cargo : __cargo;
  });
};
const transferOut = (cargo = {}) => {
  const _cargo = _flatCargo(cargo);
  Object.keys(_cargo).forEach(key => {
    const __cargo = _cargo[key];
    const _store = store[key] || 0;
    const blasting = [0, __cargo];
    if (blasting.every(b => b < _store)) {
      throw new Error("爆仓");
    } else {
      store[key] -= __cargo;
    }
  });
};

现在来看看最终的结果:

感兴趣的读者可以看看在线 demo:一个简单的仓储系统