[英]Filter an array based on dynamic keys in an array of nested objects
我有一個包含嵌套對象的數組。 像這樣的東西:
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
數組,然后深入搜索每個對象以查找匹配項。 為此,您需要
類似的東西
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);
也許是這樣的? 請記住,'searchTerm' 是類型敏感的。
用法:搜索(結果,['公司名稱','產品名稱'],'x');
/**
* Returns an array of objects which contains at least one 'searchKey' whose value
* matches THE 'searchTerm'.
*/
function search( inp, searchKeys, searchTerm ) {
let retArray = [];
function rdp( inp, searchKeys, searchTerm ) {
if ( Array.isArray(inp) ) {
if (inp.length > 0) {
inp.forEach(elem => {
rdp( elem, searchKeys, searchTerm );
});
}
}
else {
Object.keys( inp ).forEach( prop => {
if ( Array.isArray( inp[ prop ] ) || ( typeof inp[ prop ] == 'object')) {
rdp( inp[ prop ], searchKeys, searchTerm );
}
else {
searchKeys.forEach( key => {
if (( prop == key ) && // key match
( prop in inp)) { // search term found
switch ( typeof inp[prop] ) {
case 'string' : if (inp[ prop ].indexOf( searchTerm ) > -1) { retArray.push( inp ); } break;
case 'number' : if ( inp[ prop ] === searchTerm ) { retArray.push( inp ); } break;
}
}
});
}
});
}
}
rdp( inp, searchKeys, searchTerm );
return retArray;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.