margherita pizza
margherita pizza

Reputation: 7145

Javascript filter out for a category

I have an array of objects.

const regions = [
{id:1,region_name:"Western province",region_parent_id:null},
{id:2,region_name:"Colombo",region_parent_id:1},
{id:3,region_name:"Gampaha",region_parent_id:1},
{id:4,region_name:"Kaluthara",region_parent_id:1},
{id:5,region_name:"Nugegoda",region_parent_id:2},
{id:6,region_name:"Maharagama",region_parent_id:2},
{id:7,region_name:"Central province",region_parent_id:null},
{id:8,region_name:"Kandy",region_parent_id:7},
{id:9,region_name:"Mathale",region_parent_id:7},
{id:10,region_name:"theldeniya",region_parent_id:8},
{id:11,region_name:"penideniya",region_parent_id:8}

]

console.log("PROVINCES",regions.filter(e=> !e.region_parent_id));

// get districts
let province_ids = []
regions.forEach(e=>{
  if(!e.region_parent_id){
    province_ids.push(e.id)
  }
})

console.log("PROVINCE IDS",province_ids)

regions.forEach(e=>{
  if(province_ids.includes(e.region_parent_id)){
    console.log(e.region_name,"IS A DISTRICT")
  }
})

These objects can be categorized into 3 types.

  1. Province
  2. District
  3. City

Relationship is City belongs to a District, District belongs to a Province.

I could get Provinces, districts easily like this.

Can you please tell me how can I get cities?

Upvotes: 0

Views: 111

Answers (4)

程序员的键盘
程序员的键盘

Reputation: 11

const regions = [
{id:1,region_name:"Western province",region_parent_id:null},
{id:2,region_name:"Colombo",region_parent_id:1},
{id:3,region_name:"Gampaha",region_parent_id:1},
{id:4,region_name:"Kaluthara",region_parent_id:1},
{id:5,region_name:"Nugegoda",region_parent_id:2},
{id:6,region_name:"Maharagama",region_parent_id:2},
{id:7,region_name:"Central province",region_parent_id:null},
{id:8,region_name:"Kandy",region_parent_id:7},
{id:9,region_name:"Mathale",region_parent_id:7},
{id:10,region_name:"theldeniya",region_parent_id:8},
{id:11,region_name:"penideniya",region_parent_id:8}

];

function find(obj,index=0){
  if(obj.region_parent_id){return find(regions.filter(r=>r.id==obj.region_parent_id)[0],++index);} return index;
}

regions.forEach(r=>{
	let index=find(r);	
	if(index==0){console.log(`Province ${r.region_name}`);}if(index==1){console.log(`District ${r.region_name}`);}if(index==2){console.log(`City ${r.region_name}`);}
});

Upvotes: 1

M M
M M

Reputation: 725

console.log("CITIES",regions.filter(e=> (e.region_parent_id && regions.find(x=> x.id==e.region_parent_id).region_parent_id!=null)));

returns

CITIES 
(4) [{…}, {…}, {…}, {…}]
0: {id: 5, region_name: "Nugegoda", region_parent_id: 2}
1: {id: 6, region_name: "Maharagama", region_parent_id: 2}
2: {id: 10, region_name: "theldeniya", region_parent_id: 8}
3: {id: 11, region_name: "penideniya", region_parent_id: 8}`

PS - there is a simple hack in your case though. Once you have filtered out the Provinces and Districts, the remaining ones in the parent array are all cities. No need for complex JS queries.

Upvotes: 1

Mark
Mark

Reputation: 92440

You can start at the top level and filter the array for each sub level. Each time save a set of the ids so you can find the children by looking up their ids in the parent set in constant time:

const regions = [{id:1,region_name:"Western province",region_parent_id:null},{id:2,region_name:"Colombo",region_parent_id:1},{id:3,region_name:"Gampaha",region_parent_id:1},{id:4,region_name:"Kaluthara",region_parent_id:1},{id:5,region_name:"Nugegoda",region_parent_id:2},{id:6,region_name:"Maharagama",region_parent_id:2},{id:7,region_name:"Central province",region_parent_id:null},{id:8,region_name:"Kandy",region_parent_id:7},{id:9,region_name:"Mathale",region_parent_id:7},{id:10,region_name:"theldeniya",region_parent_id:8},{id:11,region_name:"penideniya",region_parent_id:8}]
    
let provinces = regions.filter(e => !e.region_parent_id)
let province_id = new Set(provinces.map(p => p.id))

let region = regions.filter(e => province_id.has(e.region_parent_id))
let region_id = new Set(region.map(r => r.id))

let cities = regions.filter(r => region_id.has(r.region_parent_id))

console.log("provinces:", provinces)
console.log("regions:", region)
console.log("cities:", cities)

Upvotes: 1

Robby Cornelissen
Robby Cornelissen

Reputation: 97150

You can use Array.prototype.some() like this:

const regions = [
  {id:1,region_name:"Western province",region_parent_id:null},
  {id:2,region_name:"Colombo",region_parent_id:1},
  {id:3,region_name:"Gampaha",region_parent_id:1},
  {id:4,region_name:"Kaluthara",region_parent_id:1},
  {id:5,region_name:"Nugegoda",region_parent_id:2},
  {id:6,region_name:"Maharagama",region_parent_id:2},
  {id:7,region_name:"Central province",region_parent_id:null},
  {id:8,region_name:"Kandy",region_parent_id:7},
  {id:9,region_name:"Mathale",region_parent_id:7},
  {id:10,region_name:"theldeniya",region_parent_id:8},
  {id:11,region_name:"penideniya",region_parent_id:8}
];

const provinces = regions.filter(r => r.region_parent_id == null);
const districts = regions.filter(r => provinces.some(p => p.id === r.region_parent_id));
const cities = regions.filter(r => districts.some(d => d.id === r.region_parent_id));

console.log("Provinces: ", provinces);
console.log("Districts: ", districts);
console.log("Cities: ", cities);

Not the most efficient approach to be sure, but should not pose any problems as long as your list of regions is relatively short.

Upvotes: 2

Related Questions