【问题标题】:What is the most efficent way to filter an object with an array of arrays?用数组数组过滤对象的最有效方法是什么?
【发布时间】:2017-07-04 07:36:27
【问题描述】:

我试图通过一个数组来过滤一个对象,得到一个对象数组。

像这样:

 let obj =
{
  "a.1":1,
  "a.2":2,
  "b.1":3,
  "b.2":4,
  "c.1":5,
  "c.2":6
}

let array = 
[
  ["a.1","b.1"],
  ["a"],
  ["b","c.1"]
]

let expectedResult = 
[
  {
    "a.1":1,
    "b.1":3,
  },
  {
    "a.1":1,
    "a.2":2,
  },
  {
    "b.1":3,
    "b.2":4,
    "c.1":5
  },
]

// this is what I came up with
const filterObjectByArray = (obj, arr) =>
    Object.keys(obj)
    .filter(ch => {
        for (var index = 0; index < arr.length; index++)
            if (ch.startsWith(arr[index]))
                return true;
    })
    .reduce((ret, key) =>{
        ret[key] = obj[key]
        return ret
    },{})
    
let result = array.map(arr => filterObjectByArray(obj, arr))

//kind of deepEqual
console.log(JSON.stringify(expectedResult) == JSON.stringify(result))

有没有更简单或更方便的方法来做到这一点?我需要经常执行此操作,并且我的对象将多达数百个条目,因此我在这里看到了潜在的瓶颈。

【问题讨论】:

  • 我可能会看看 Lodash (lodash.com) 实用程序
  • 这正是我会做的。如果您需要从中获得额外的速度,我可能会通过将功能方法展开为纯程序(即没有filterreduce,只有香草for)和基准测试。但是,我还建议首先进行基准测试,看看这是否像你担心的那样慢(如果它有几百个条目,它应该相当快,除非你想要每秒百万次)。你知道,“过早的优化是万恶之源”等等。
  • 只当心startsWith - a.15a.1 开头,我怀疑这可能不是你想要的。 (ch + ".").startsWith(arr[index] + ".") 更可靠(a.15.a. 开头,但不以a.1. 开头)。
  • 创建树可能会更高效,例如a:{1:2,2:3},b: ... 这样您可以更轻松地过滤。
  • @Amadan 感谢您的提示,我会调查一下

标签: javascript arrays performance sorting object


【解决方案1】:

我会创建一个“基础”(字母)到“真实”键的单一类型映射,然后在创建对象时使用它将字母转换为真实键。

const obj = {
  "a.1": 1,
  "a.2": 2,
  "b.1": 3,
  "b.2": 4,
  "c.1": 5,
  "c.2": 6
};

const array = [
  ["a.1", "b.1"],
  ["a"],
  ["b", "c.1"]
];

const getBaseKey = (key) => key.match(/^[a-z]+/)[0]; // get the base of the key - the letter. If it's only one letter, you can use key[0]

/** create a one time map of keys by their base **/
const oobjKeysMap = Object.keys(obj).reduce((map, key) => {
  const baseKey = getBaseKey(key);
  const curr = map.get(baseKey) || [];
  curr.push(key);
  return map.set(baseKey, curr);
}, new Map());

const result = array.map((sub) => // iterate the array
  [].concat(...sub.map((k) => k in obj ? k : oobjKeysMap.get(getBaseKey(k)))) // create the least of "real" keys
  .reduce((ret, key) => { // create the object
    ret[key] = obj[key];
    return ret;
  }, {})
);

console.log(result);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多