问题描述
我有如下数据数组。
一个大陆数组,每个大陆都有一个地区数组,每个大陆都有一个国家数组。例如
continents:[
{
Name: 'Europe',Regions: [
{
Name: Western Europe,Countries: [
{
Name: 'United Kingdom'
},{
Name: 'Republic of Ireland'
}
]
}
]
}
]
我有一个搜索字段,用户可以在其中搜索一个国家/地区。 我需要做的是能够过滤结果以仅显示国家/地区的搜索,但同时显示地区和大洲。
Europe
-> Western Europe
-> **United** Kingdom
Americas
-> north America
-> **United** States of America
我撞墙了。任何建议将不胜感激。
谢谢
解决方法
查看给定的数据结构和 OP 的任务,一个人必须做的第一件事是(恰好一次)重新组装或将给定的结构reduce
变成一个国家项目的平面列表,其中每个项目除了它的country
字段还包含该国家/地区的 region
和 continent
属性......类似这样......
...,{
country: "Republic of Ireland",region: "Western Europe",continent: "Europe"
},{
country: "Indonesia",region: "Southeast Asia",continent: "Asia"
},...
然后可以以非常简单的方式实现仍然开放的搜索/查询任务,filter
寻找任何项目的小写名称includes同样lowercase名称查询...
function queryCountryListByName(nameQuery) {
return listOfCountryItems.filter(item =>
item.country.toLowerCase().includes(nameQuery.toLowerCase())
);
}
function createAndCollectCountryItemWithContext(list,item) {
//const context = this; // e.g. { continent: 'Europe',region: 'Western Europe' }
return list.concat(
Object.assign({ country: item.Name },this)
);
}
function createAndCollectCountryItemFromRegionWithContext(list,item) {
//const context = this; // e.g. { continent: 'Europe' }
return list.concat(
item.Countries.reduce(
createAndCollectCountryItemWithContext.bind(
Object.assign({ region: item.Name },this)
),[]
)
);
}
function createAndCollectCountryItemFromRegionAndContinent(list,item) {
return list.concat(
item.Regions.reduce(
createAndCollectCountryItemFromRegionWithContext.bind({
continent: item.Name,}),[]
)
);
}
const contriesGroupedByRegiosAndContinents = [{
Name: 'Europe',Regions: [{
Name: 'Western Europe',Countries: [{
Name: 'United Kingdom',},{
Name: 'Republic of Ireland',}],{
Name: 'Asia',Regions: [{
Name: 'Southeast Asia',Countries: [{
Name: 'Indonesia',{
Name: 'Philippines',{
Name: 'Americas',Regions: [{
Name: 'North America',Countries: [{
Name: 'United States of America',{
Name: 'Canada',}];
const listOfCountryItems = contriesGroupedByRegiosAndContinents.reduce(
createAndCollectCountryItemFromRegionAndContinent,[]
);
console.log('listOfCountryItems ...',listOfCountryItems);
function queryCountryListByName(nameQuery) {
return listOfCountryItems.filter(item =>
item.country.toLowerCase().includes(nameQuery.trim().toLowerCase())
);
}
console.log(
"queryCountryListByName(' united ') ...",queryCountryListByName(' united ')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
我们可以首先使用 Array.some 过滤大洲(对于地区和国家),然后循环匹配的大洲以记录结果:
// The string to search for.
let str = "United"
continents = [
{
Name: 'Europe',Regions: [
{
Name: 'Western Europe',Countries: [
{
Name: 'United Kingdom'
},{
Name: 'Republic of Ireland'
}
]
}
]
},{
Name: 'Americas',Regions: [
{
Name: 'North America',Countries: [
{
Name: 'Canada'
},{
Name: 'United States of America'
}
]
}
]
}
]
// Find all continents with matching countries
let matchingContinents = continents.filter(continent => continent.Regions.some(region => region.Countries.some(country => country.Name.includes(str))));
for(let continent of matchingContinents) {
console.log(continent.Name);
for(let region of continent.Regions) {
console.log(" -> " + region.Name);
for(let country of region.Countries) {
if (country.Name.includes(str)) {
console.log(" -> " + country.Name.replace(str,'**' + str + '**'));
}
}
}
}
所以据我所知,您想获取大量对象并返回具有相同结构的过滤版本吗?如果是这样,你可以这样做。
const continents = [{
Name: 'Europe',}];
const result = continents.map(con => {
if(con.Regions.some(reg => reg.Countries.some(c => c.Name.startsWith('United')))){
return {
...con,Regions: con.Regions.map(reg => {
if(reg.Countries.some(c => c.Name.startsWith('United'))){
return {
...reg,Countries: reg.Countries.filter(c => c.Name.startsWith('United'))
}
}
})
}
}
});
console.log(result);
.as-console-wrapper { min-height: 100%!important; top: 0; }
显然,您希望将 'United'
替换为您的搜索词。