我有一个包含嵌套对象的数组。像这样:
const results = [
{
general: {
orderID: '5567',
created: 1548765626101,
status: 'new'
},
company: {
companyName: 'company x',
companyEmail: 'info@companyx.com',
companyContact: 'John Doe'
},
customer: {
customerName: 'Jane Doe',
customerEmail: 'janedoe@email.com'
},
products: [
{
productID: 4765756,
productName: 'Product x',
productDescription: 'Description for product x'
},
{
productID: 4767839,
productName: 'Product y',
productDescription: 'Description for product y'
}
],
payment: {
price: 1000,
method: 'cash'
}
},
]
(为了让它有点结构化,我只为这个问题插入了一个结果对象。但假设结果数组中有 100 个元素。)
用户可以输入搜索词并选中/取消选中将包含或排除这些键的键。键被硬编码在列表中。
举个例子。用户键入“jane”并检查 customerName 和 customerEmail 作为要搜索的关键字。或者用户输入“x”并检查产品名称。
如何动态搜索这些选中的键?我已经将选定的键放入数组中。
所以对于第一个示例,我有 ['customerName', 'customerEmail']
。
第二个是 ['productName']
我之前对硬编码键使用过 array.filter()
但我不知道如何过滤这些动态键。
谁能帮我分解一下不同的步骤?我正在使用 es6,没有外部库。
最佳答案
您需要遍历 results
数组,然后深入搜索每个对象以找到匹配项。为此你需要
- 获取所有键/值对
- 如果值为对象,则进行更深入的搜索
- 如果值是数组,则更深入地搜索每个项目
- 否则(值为字符串或数字)
- 如果关键字在要搜索的字段列表中
- 如果值与查询匹配则返回 true
- 否则返回false
类似的东西
const deepSearcher = (fields, query) =>
function matcher(object) {
const keys = Object.keys(object);
return keys.some(key => {
const value = object[key];
// handle sub arrays
if (Array.isArray(value)) return value.some(matcher);
// handle sub objects
if (value instanceof Object) return matcher(value);
// handle testable values
if (fields.includes(key)) {
// handle strings
if (typeof value === "string") return value.includes(query);
// handle numbers
return value.toString() === query.toString();
}
return false;
});
};
此函数创建一个与 .filter
方法一起使用的匹配器。
const customerFilter = deepSearcher(['customerName', 'customerEmail'], 'jane')
const found = results.filter(customerFilter);
或者您可以将其直接传递给 .filter
const found = results.filter(deepSearcher(['customerName', 'customerEmail'], 'jane'));
您传递给 deepSearcher 的字段不必属于同一个对象。匹配器将测试任何匹配项(但它们必须指向字符串/数字才能使此代码正常工作)。
工作测试用例
const results = [{
general: {
orderID: "5567",
created: 1548765626101,
status: "new"
},
company: {
companyName: "company x",
companyEmail: "info@companyx.com",
companyContact: "John Doe"
},
customer: {
customerName: "Jane Doe",
customerEmail: "janedoe@email.com"
},
products: [{
productID: 4765756,
productName: "Product x",
productDescription: "Description for product x"
},
{
productID: 4767839,
productName: "Product y",
productDescription: "Description for product y"
}
],
payment: {
price: 1000,
method: "cash"
}
}];
const deepSearcher = (fields, query) =>
function matcher(object) {
const keys = Object.keys(object);
return keys.some(key => {
const value = object[key];
// handle sub arrays
if (Array.isArray(value)) return value.some(matcher);
// handle sub objects
if (value instanceof Object) return matcher(value);
// handle testable values
if (fields.includes(key)) {
// handle strings
if (typeof value === "string") return value.includes(query);
// handle numbers
return value.toString() === query.toString();
}
return false;
});
};
const matchingCustomer = results.filter(deepSearcher(["customerName", "customerEmail"], 'jane'));
console.log('results with matching customer:', matchingCustomer.length);
const matchingProduct = results.filter(deepSearcher(["productName"], 'x'));
console.log('results with matching product:', matchingProduct.length);
const matchingPrice = results.filter(deepSearcher(["price"], '1000'));
console.log('results with matching price:', matchingPrice.length);
const nonMatchingPrice = results.filter(deepSearcher(["price"], '500'));
console.log('results with non matching price:', nonMatchingPrice.length);
关于javascript - 根据嵌套对象数组中的动态键过滤数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54713462/