查找两个数组之间的预定义组合

Find Pre-defined Combinations Between Two Arrays

我有一个对象和一个数组:

"catalog" : {
    "thing" : {
         "required_components" : [ "a", "d" ]
    },
    "gadget" : {
        "required_components" : [ "e", "e" ]
    },
    "device" : {
        "required_components" : [ "d", "e" ]
    },
   "entity" : {
        "required_components" : [ "a", "a" ]
    }
}

myComponents = ["a", "d", "c", "a", "e"]

鉴于 myComponents 中列出的组件,我想创建一个可能的目录项数组。

我目前正在遍历 catalog 并使用 .filter() 获取 myComponentsrequired_components 的交集:

console.log(requiredComponents.filter(x => myComponents.includes(x))) //Outputs ["a", "d"]

然后如果 requiredComponents.filter(x => myComponents.includes(x)).length == 2,我将当前迭代的目录项推送到一个数组。

但这看起来很笨拙,并且会产生一些不希望的和意外的结果。

首先,因为我是在一个循环中进行的,所以它会将多个重复项推送到数组中。我可以用更笨重的代码来克服这个问题。

其次,我最终得到了我没有组件的目录项。例如,如果我有 ["a", "a"] 我会以某种方式在我的输出数组中以 thing 结束。也许这与它也在循环中发生的事实有关。

无论如何,必须有更简洁的方法来做到这一点。

let catalog = [["a", "d"],["e", "e"], ["d","e"], ["a", "a"]];
let myComponents = ["a", "d", "c", "a"];
let possibleComponents = [];

catalog.forEach(item => {
  possibleComponents.push(item.filter(x => myComponents.includes(x)));
});
console.log(possibleComponents);

问题似乎来自比较数组时的重复项。

这是一个带有 lodash 的简短原型:

import _ from 'lodash'

// Check if subset is included in superset (respecting duplicates).
const isSubset = (subset, superset) => {
  const subsetCount = _.countBy(subset)
  const supersetCount = _.countBy(superset)

  return _.every(subsetCount, (count, value) => supersetCount[value] >= count)
}

// Filter all catalog items, that could be build by myComponents
const matches = _.pickBy(catalog, ({required_components}, thing) => isSubset(required_components, myComponents))

// Get only the names of the catalog items
const names = _.keys(matches)