代码之家  ›  专栏  ›  技术社区  ›  Vahid Hallaji

如何在javascript中将相同的键值对(以不同的顺序)表示为映射的相同键?[副本]

  •  0
  • Vahid Hallaji  · 技术社区  · 6 年前

    这个问题已经有了答案:

    我有一个接受配置并返回值的逻辑。但是,我想从缓存中检索相同配置的进一步尝试。密钥的顺序可以在配置中改变,但必须视为相同的配置。

    评论解释了我试图达到的目标。我希望只有两个开口,因为在示例代码中只有两个不同的配置。只有第一次和第二次尝试 open() 按预期进行,因为同一对象作为键传递到映射。

    如果我试图将键保留为json字符串,那么键的顺序可能会有问题。

    这是我到目前为止所做的努力。我欣赏任何想法或其他解决方案。

    var m = new Map();
    
    function opening(config) {
      // ...
      return "foo";
    }
    
    function open(config = {}) {
    
      if (!m.has(config)) {
        m.set(config, opening(config));
        console.log("open and set: ", config);
      } else {
        console.log("get from the map: ", config);
      }
    
      return m.get(config);
    }
    
    var c1 = { a: 1, b: 2 };
    
    open(c1); // open and set [OK]
    open(c1); // get from the map [OK] 
    open({ a: 1, b: 2 }); // get from the map
    open({ b: 2, a: 1 }); // get from the map, even in different orders
    open({ a: 1, b: 2, c: 3 }); // open and set
    open({ a: 1, c: 3, b: 2 }); // get from the map
    1 回复  |  直到 6 年前
        1
  •  1
  •   CertainPerformance    6 年前

    看起来您需要一种方法来表示不同的对象,以便在 map 是的。一种选择是把物体 sort 根据钥匙的字母顺序输入,然后 stringify 已排序的条目:

    var m = new Map();
    
    function opening(config) {
      // ...
      return "foo";
    }
    
    function open(config = {}) {
      const key = objToKeyValStr(config);
      if (!m.has(key)) {
        m.set(key, opening(config));
        console.log("open and set: ", config);
      } else {
        console.log("get from the map: ", config);
      }
    
      return m.get(config);
    }
    function replacer(_, value) {
      if (typeof value !== 'object' || Array.isArray(value)) return value;
      return objToKeyValStr(value);
    }
    const objToKeyValStr = obj => (
      JSON.stringify(
        Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])),
        replacer
      )
    );
    
    var c1 = { a: 1, b: 2 };
    
    open(c1); // open and set [OK]
    open(c1); // get from the map [OK] 
    open({ a: 1, b: 2 }); // get from the map
    open({ b: 2, a: 1 }); // get from the map, even in different orders
    open({ a: 1, b: 2, c: 3 }); // open and set
    open({ a: 1, c: 3, b: 2 }); // get from the map
    
    open({ a: 1, b: { c: 1, d: 1 }}); // open and set
    open({ a: 1, b: { d: 1, c: 1 }}); // get from the map