如何筛选项目列表取决于另一个列表



我有一个脚本数组"列表";以及选择的用户的阵列";用户";,每个用户可以有几个这样的脚本。

如何过滤";列表";脚本,只为其中的正确语句保留这些脚本:

  • 如果用户列表中至少有人没有来自该列表的脚本"列表">
    我们显示此脚本
  • 如果所有用户都有这样的脚本,我们不会显示它

示例

let list = [{name: 'script1', id:'1'}, {name: 'script2',id:'2'},{name: 'script3',id:'3'}]
let users = [
{name: 'user1', scripts:[{name: 'script1',id:'1'}]},
{name: 'user2', scripts:[{name: 'script1',id:'1'},{name: 'script2',id:'2'}]}
]
let result = list.filter(...)  //=> let list = [{name: 'script2'},{name: 'script3'}]

我的尝试看起来很糟糕

let result = list.filter(item => {
return  users.filter(user => {
return user.scripts.some(el => {
return el.id !== item.id
})
})
})

当你想找到一个完全缺少搜索项的数组时,你会犯一个常见的错误,那就是寻找不等于搜索项的东西。它们并不等价,因为即使一个元素不等于搜索项,其他元素也可能相等。

使用!users.every(...)检查至少一个用户是否缺少某些内容。

let list = [{name: 'script1', id:'1'}, {name: 'script2',id:'2'},{name: 'script3',id:'3'}]
let users = [
{name: 'user1', scripts:[{name: 'script1',id:'1'}]},
{name: 'user2', scripts:[{name: 'script1',id:'1'},{name: 'script2',id:'2'}]}
]
let result = list.filter(({id}) =>
!users.every(({scripts}) => scripts.some(s => s.id == id)));
console.log(result);

  1. users数组上使用Array#reduce,创建一个Mapkey作为脚本idvalue作为拥有它的users的编号
  2. list数组上使用Array#filter,获取未被所有users使用的scripts,然后,如果您只想返回具有name的对象,请使用Array#map

const list = [
{ name: 'script1', id:'1' }, 
{ name: 'script2', id:'2' },
{ name: 'script3', id:'3' }
];
const users = [
{ name: 'user1', scripts:[ { name: 'script1', id:'1' } ] },
{ name: 'user2', scripts:[ { name: 'script1', id:'1' }, { name: 'script2', id:'2' } ] }
];
const TOTAL = users.length;
const usage = users.reduce((scriptUsagesMap, { scripts=[] }) => {
scripts.forEach(({ id }) => {
const count = scriptUsagesMap.get(id) || 0;
scriptUsagesMap.set(id, count + 1);
});
return scriptUsagesMap;
}, new Map);
const result = list
.filter(({ id }) => usage.get(id) !== TOTAL)
.map(({ name }) => ({ name }));
console.log(result);