标记系统从 ANY 到 ALL 的布尔开关

Boolean switch from ANY to ALL for tag system

我有一组项目 items[]。每个都有一个布尔值 属性 filtered 和一个 属性 是一个名为 tags[].

的数组

我还有另一个数组:selected_tags.

通过这个循环,我可以根据所选标签过滤所有项目:

items.forEach(function (item) {

    if (selected_tags.length > 0)
        tag_filter = !selected_tags.some(tag => item.tags.includes(tag));

    // ... other_filter = something else...

    item.filtered = !(!tag_filter && !other_filter);

});

这适用于 ANY 逻辑(如果任何标签在选定的标签中,则显示该项目)。我想使用 ALL 逻辑来执行此操作(如果所有选定的标签都在项目标签中,则显示它)。

所以,很自然地,我想知道 includes 是否可以做这样的事情:

[1,2,3].includes([1,2,3])

[1,2,3].includes(1,2,3)

tag_filter = item.tags.includes(selected_tags);

但它给出了错误。

我可以做到这一点,同时将它保持为一个简单的衬里,如果过滤 returns tag_filter = true 如果不过滤 false 吗?

您可以使用 .every() 而不是 .some()

例如:

[1,2,3].every(x => [1,2,3].includes(x))

此外,您可以更改

item.filtered = !(!tag_filter && !other_filter)

item.filtered = tag_filter || other_filter

Array::every()

[1, 2, 3].every(function(item) { return [1, 2, 3].includes(item)) }

或 ES6 相同:

[1, 2, 3].every(item => [1, 2, 3].includes(item))

实际上您是在检查一个数组是否是另一个数组的子集。为此,您需要使用 every()includes()。时间复杂度为 O(m * n)

function isSubsetOf(a, b){
  return b.every(x => a.includes(x));
}
console.log(isSubsetOf([1,2,3], [1,2,3]))
console.log(isSubsetOf([1,2,3], [1,2,3, 4]))

对于线性O(N)时间复杂度首先将主数组转换为Set然后使用Set.prototype.has

function isSubsetOf(a, b){
  a = new Set(a)
  return b.every(x => a.has(x));
}
console.log(isSubsetOf([1,2,3], [1,2,3]))
console.log(isSubsetOf([1,2,3], [1,2,3, 4]))

所以基本上,您正在寻找比 some() 更严格的东西,也就是说 every()。所以简单地改变这个:

tag_filter = !selected_tags.some(tag => item.tags.includes(tag));

为此:

tag_filter = !selected_tags.every(tag => item.tags.indexOf(tag) !== -1);

这篇文章 item.tags.indexOf(tag) !== -1 可以理解为“tag 存在于 item.tags 中,所以它的索引不是 -1”。

希望对您有所帮助!