[英]Return object comparing input with nested objects
I am having an object that looks like this:我有一个 object,看起来像这样:
const obj = {
"cat1" : {
id: "1",
name: "Category1",
tiles: [{ tileName: "abc", searchable: true}, { tileName: "def", searchable: true}]
},
"cat2" : {
id: "2",
name: "Category2",
tiles: [{ tileName: "ab", searchable: true}, { tileName: "lmn", searchable: true}]
},
"cat3" : {
id: "3",
name: "Category3",
tiles: [{ tileName: "pqr", searchable: true}, { tileName: "", searchable: false}]
}
}
Based on the search input, I need to check if the search item is included in each object basically inside two fields.基于搜索输入,我需要检查搜索项是否包含在每个 object 中,基本上在两个字段内。 One is
name
and the other is tileName
inside tile
array ( should be searched only if that object has searchable
true ).一个是
name
,另一个是tile
数组中的tileName
(仅当 object 具有searchable
的 true 时才应搜索)。 It should be searched across name
and tiles
array应该在
name
和tiles
数组中搜索
When search is "ab", the output should be当搜索是“ab”时,output应该是
const obj = {
"cat1" : {
id: "1",
name: "Category1",
tiles: [{ tileName: "abc", searchable: true}]
},
"cat2" : {
id: "2",
name: "Category2",
tiles: [{ tileName: "ab", searchable: true}]
},
}
Code that I tried我试过的代码
function handleSearch(search)
{
return Object.values(obj).map((item) => {
if(item["name"].toLowerCase().includes(item.toLowerCase()))
return item;
})
})
}
I would personally create a generic filterMap()
helper that combines the functionalities of both filter()
and map()
我会亲自创建一个通用的
filterMap()
助手,它结合了filter()
和map()
的功能
// Combines filter() and map(). If no value is returned from the callback
// function (undefined) then the value is removed from the result. If a
// non-undefined value is returned, then that value is used as the map
// value. Returns a new array with the filtered/mapped values.
//
// filterMap([1,2,3,4,5], (n) => { if (n % 2) return n * n })
// //=> [1,9,25]
//
function filterMap(iterable, fn) {
const filterMapped = [];
for (const item of iterable) {
const mapped = fn(item);
if (mapped === undefined) continue; // skip current iteration
filterMapped.push(mapped);
}
return filterMapped;
}
With the above helper defined you can get the desired functionality with relative ease使用上面定义的帮助程序,您可以相对轻松地获得所需的功能
function search(searchString, object) {
const searchIn = (whole, part) => whole.toLowerCase().includes(part.toLowerCase());
return Object.fromEntries(
filterMap(Object.entries(object), ([key, { tiles, ...category }]) => {
// If the category name matches, return the whole category as is,
// without filtering the tiles.
if (searchIn(category.name, searchString)) {
return [key, { ...category, tiles }];
}
// If the category name did not match, filter the tiles.
const matchingTiles = tiles.filter((tile) => (
tile.searchable && searchIn(tile.tileName, searchString)
));
// If there are one or more matching tiles found, return the
// category with only the matching tiles.
if (matchingTiles.length) {
return [key, { ...category, tiles: matchingTiles }];
}
// If neither the category name nor one of the tiles matched,
// nothing (undefined) is returned, thus the entry is removed
// from the result.
})
);
}
function search(searchString, object) { const searchIn = (whole, part) => whole.toLowerCase().includes(part.toLowerCase()); return Object.fromEntries( filterMap(Object.entries(object), ([key, { tiles, ...category }]) => { // If the category name matches, return the whole category as is, // without filtering the tiles. if (searchIn(category.name, searchString)) { return [key, {...category, tiles }]; } // If the category name did not match, filter the tiles. const matchingTiles = tiles.filter((tile) => ( tile.searchable && searchIn(tile.tileName, searchString) )); // If there are one or more matching tiles found, return the // category with only the matching tiles. if (matchingTiles.length) { return [key, {...category, tiles: matchingTiles }]; } // If neither the category name nor one of the tiles matched, // nothing (undefined) is returned, thus the entry is removed // from the result. }) ); } const obj = { "cat1": { id: "1", name: "Category1", tiles: [ { tileName: "abc", searchable: true }, { tileName: "def", searchable: true }, ], }, "cat2": { id: "2", name: "Category2", tiles: [ { tileName: "ab", searchable: true }, { tileName: "lmn", searchable: true }, ], }, "cat3": { id: "3", name: "Category3", tiles: [ { tileName: "pqr", searchable: true }, { tileName: "", searchable: false }, ], }, }; console.log('search "ab"', search("ab", obj)); console.log('search "3"', search("3", obj)); // helper // Combines filter() and map(). If no value is returned from the callback // function (undefined) then the value is removed from the result. If a // non-undefined value is returned, then that value is used as the map // value. Returns a new array with the filtered/mapped values. // // filterMap([1,2,3,4,5], (n) => { if (n % 2) return n * n }) // //=> [1,9,25] // function filterMap(iterable, fn) { const filterMapped = []; for (const item of iterable) { const mapped = fn(item); if (mapped === undefined) continue; // skip current iteration filterMapped.push(mapped); } return filterMapped; }
In the above code we use Object.entries()
to convert the object to an array.在上面的代码中,我们使用
Object.entries()
将 object 转换为数组。 The array is then transformed using our newly defined filterMap()
method.然后使用我们新定义的
filterMap()
方法转换数组。 Finally the resulting array is transformed back into an object using Object.fromEntries()
.最后,使用
Object.fromEntries()
将生成的数组转换回 object。
The code makes use of destructuring , the spread syntax in object literals , and the property definition shorthand .该代码使用解构、 object 文字中的扩展语法和属性定义速记。
For those using TypeScript, filterMap()
should be defined like:对于那些使用 TypeScript 的用户,
filterMap()
应该定义如下:
function filterMap<A, B>(iterable: Iterable<A>, fn: (item: A) => undefined | B): B[] {
const filterMapped: B[] = [];
for (const item of iterable) {
const mapped = fn(item);
if (mapped === undefined) continue; // skip current iteration
filterMapped.push(mapped);
}
return filterMapped;
}
The answer might still leave you with:答案可能仍然留给你:
Not all code paths return a value.
并非所有代码路径都返回一个值。 (7030)
(7030)
In which case you must either explicitly return from the callback function.在这种情况下,您必须显式地从回调 function 中返回。
// ...
// If neither the category name nor one of the tiles matched,
// nothing (undefined) is returned, thus the entry is removed
// from the result.
return; // <- explicit return at the end
})
Or alternatively set "noImplicitReturns": false
in your TypeScript settings, to allow implicit returns.或者在您的 TypeScript 设置中设置
"noImplicitReturns": false
,以允许隐式返回。
const obj = {"cat1":{"id":"1","name":"Category1","tiles":[{"tileName":"abc","searchable":true},{"tileName":"def","searchable":true}]},"cat2":{"id":"2","name":"Category2","tiles":[{"tileName":"ab","searchable":true},{"tileName":"lmn","searchable":true}]},"cat3":{"id":"3","name":"Category3","tiles":[{"tileName":"pqr","searchable":true},{"tileName":"","searchable":false}]}}
function search(obj, text) {
return Object.values(obj)
.map((item) => ({
...item,
tiles: item.tiles.filter(tile => tile.searchable && tileName.includes(text))
}))
.filter(({tiles}) => tiles.length)
}
console.log(search(obj, 'ab'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.