我想过滤一个给定过滤器对象的数组
function remove (array, filter) {
// magic
}
filter
是一个可变大小的对象,具有任意数量的键/值
它应该像下面这样做
const products = [
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'S', color: 'red' },
{ size: 'L', color: 'green' },
]
// With a filter of keys/value it filters for the existing key/values
const filteredProducts1 = remove(products, { size: 'S', color: 'red' })
console.log(filteredProducts1)
/*
[
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'L', color: 'green' },
]
*/
// With less key/value than the object array, it filters for the existing key/value
const filteredProducts2 = remove(products, { size: 'S' })
console.log(filteredProducts2)
/*
[
{ size: 'L', color: 'red' },
{ size: 'L', color: 'green' },
]
*/
// With more keys/values than the object array it discard the non-existing key/value
const filteredProducts1 = remove(products, { size: 'S', color: 'red', type: 'dress' })
console.log(filteredProducts1)
/*
[
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'L', color: 'green' },
]
*/
我的问题是从过滤器对象
建立一个动态条件我正在尝试转换
{ key1: value1, key2: value2, ... , keyN: valueN }
到
condition 1 && condition2 && ... & conditionN
如果至少存在一个条件且不等于filter,则可以使用some
返回true。
你甚至可以使用x[k]
代替x.hasOwnProperty(k)
,如果保证会有键指向具有假值的值(undefined
,null
,0
..)(8)。
如果您的环境(浏览器/节点)支持Object.hasOwn
而不是Object.hasOwnProperty
,则MDN建议使用CC_9。
function remove (array, filter) {
return array.filter((x) => Object.entries(filter).some(([k,v]) => x.hasOwnProperty(k) && x[k] !== v))
}
const products = [
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'S', color: 'red' },
{ size: 'L', color: 'green' },
]
console.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))
.as-console-wrapper { max-height: 100% !important; top: 0; }
编辑修复
remove(products, {type: 'dress'})删除所有不应该删除的内容
现在我从对象中存在的过滤器项中过滤出字段来检查如果过滤器项为空,则返回整个数组
function remove (array, filter) {
return array.filter((x,i) => {
const entries = Object.entries(filter).filter(([k,_]) => x.hasOwnProperty(k))
if (entries.length === 0) return array
return entries.some(([k,v]) => x[k] !== v)
})
}
const products = [
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'S', color: 'red' },
{ size: 'L', color: 'green' },
]
console.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))
console.log(remove(products, { type: 'dress' }))
console.log(remove(products, {}))
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以确定过滤器中的任何键值对是否存在于数组中的每个对象中:
function remove(array, filter) {
return array.filter((obj) => {
for (const [key, value] of Object.entries(filter)) {
if (obj[key] === value) return false;
}
return true;
});
}
const products = [
{ size: "M", color: "blue" },
{ size: "S", color: "blue" },
{ size: "L", color: "red" },
{ size: "S", color: "red" },
{ size: "L", color: "green" },
];
console.log(remove(products, { size: "S", color: "red" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "green" } ]
console.log(remove(products, { size: "S" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "red" }, { size: "L", color: "green" } ]
console.log(remove(products, { size: "S", color: "red", type: "dress" }));
// [ { size: "M", color: "blue" }, { size: "L", color: "green" } ]
这个怎么样,变量过滤器将返回匹配过滤器的布尔数组[真,假,真]等。如果过滤器变量
中包含false,则返回数组项const products = [
{ id: 1, size: 'S', color: 'blue', type: 'dress' },
{ id: 2, size: 'L', color: 'red', type: 'dress' },
{ id: 3, size: 'S', color: 'red', type: 'dress' },
{ id: 4, size: 'L', color: 'green', type: 'shirt' },
]
const filter1 = { size: 'S', color: 'red' }
const filter2 = { size: 'S' }
const filter3 = { size: 'S', color: 'red', type: 'dress' }
const remove = (products, filter) => {
return products.filter(product => {
const filters = Object.keys(filter).map(prop => {
return filter[prop] === product[prop]
})
return filters.includes(false)
})
}
const result1 = remove(products, filter1)
const result2 = remove(products, filter2)
const result3 = remove(products, filter3)
console.log(result1)
console.log(result2)
console.log(result3)
我认为你是正确的,解决问题的关键是正确实现一个函数,它可以根据传递的键值来决定是否应该删除或保留一个项目,并且应该能够动态处理你的需求。
这里有一个建议:
const shouldkeep = kvs => obj => {
for (const k in kvs)
if (k in obj && obj[k] !== kvs[k])
return true
return false
}
const remove = (array, filter) => array.filter(shouldkeep(filter))
const products = [
{ size: 'S', color: 'blue' },
{ size: 'L', color: 'red' },
{ size: 'S', color: 'red' },
{ size: 'L', color: 'green' },
]
console.log(remove(products, { size: 'S', color: 'red' }))
console.log(remove(products, { size: 'S' }))
console.log(remove(products, { size: 'S', color: 'red', type: 'dress' }))
关于这个实现的一些注意事项:
- 函数
shouldkeep
的思想是,它遍历过滤器对象的键,并且只有当它遍历所有键而没有完全匹配值 时才返回true(这意味着"keep") - 这个语法
shouldkeep = kvs => obj =>
可能看起来很奇怪,但它实际上非常有用。它被称为柯里化,这意味着您可以将一个参数应用于函数,并返回期望下一个参数的函数。有了这个,你可以做一些类似products, {size: 'S'})
的事情,它返回一个函数,你可以把它用作filter
的参数。整洁!