2

I need to return the string with category and type together when use input the type id(which is unique) , I am pretty much done with that but I am unable to fetch root category . My solution return 'Terrace' but I need 'Rural / Terrace'.

I think I am making things over complicated

let obj =[
  {
    category: 'Residential',
    category_id: 1,
    types: [{name: 'House', id: 1},{name: 'Townhouse / Villa', id: 3},{name: 'House and Land', id: 5},{name: 'Duplex', id: 4},{name: 'Land', id: 6},{name: 'Terrace', id: 16},{name: 'Apartment/Unit', id: 2},{name: 'Relocatable', id: 7}]
  },
  {
    category: 'Commercial',
    category_id: 2,
    types: [{name: 'Office', id: 12},{name: 'House', id: 8},{name: 'Land', id: 9},{name: 'Shop', id: 10},{name: 'Factory', id: 11}]
  },
  {
    category: 'Rural',
    category_id: 3,
    types: [{name: 'House', id: 17},{name: 'House and Land', id: 14},{name: 'Land', id: 13},{name: 'Terrace', id: 15}]
  }
];
console.log(obj.map(o=>o.types).reduce((acc, val) => acc.concat(val), []).find(inner_obj=>inner_obj.id==15).name);

3 Answers 3

1

I might try something like this. Use reduce() to go through the main items, then use find() to see if you have a matching item. If so, push what you need to the array.

let obj =[{category: 'Residential',category_id: 1,types: [{name: 'House', id: 1},{name: 'Townhouse / Villa', id: 3},{name: 'House and Land', id: 5},{name: 'Duplex', id: 4},{name: 'Land', id: 6},{name: 'Terrace', id: 16},{name: 'Apartment/Unit', id: 2},{name: 'Relocatable', id: 7}]},  {category: 'Commercial',category_id: 2,types: [{name: 'Office', id: 12},{name: 'House', id: 8},{name: 'Land', id: 9},{name: 'Shop', id: 10},{name: 'Factory', id: 11}]},{category: 'Rural',category_id: 3,types: [{name: 'House', id: 17},{name: 'House and Land', id: 14},{name: 'Land', id: 13},{name: 'Terrace', id: 15}]}];

let found = obj.reduce((a, c) => {
    let found = c.types.find(t => t.id === 15)
    if (found) a.push({category: c.category, name:found.name})
    return a
}, [])
  
console.log(found)

I could potentially return more than one item if there was more than one item with id===15. In this case it's not clear what should happen, but returning them all seems reasonable.

EDIT: if you know id is unique

If you know there is only one of each id, you can exit early, which might save some time in big searches:

let obj =[{category: 'Residential',category_id: 1,types: [{name: 'House', id: 1},{name: 'Townhouse / Villa', id: 3},{name: 'House and Land', id: 5},{name: 'Duplex', id: 4},{name: 'Land', id: 6},{name: 'Terrace', id: 16},{name: 'Apartment/Unit', id: 2},{name: 'Relocatable', id: 7}]},  {category: 'Commercial',category_id: 2,types: [{name: 'Office', id: 12},{name: 'House', id: 8},{name: 'Land', id: 9},{name: 'Shop', id: 10},{name: 'Factory', id: 11}]},{category: 'Rural',category_id: 3,types: [{name: 'House', id: 17},{name: 'House and Land', id: 14},{name: 'Land', id: 13},{name: 'Terrace', id: 15}]}];

function find(id, obj) {
    for (prop of obj){
        let found = prop.types.find(t => t.id === id)
        if (found) return [prop.category, found.name]
    }
}
console.log(find(15, obj))

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks , sometimes one liners are really ugly :)
1

Why not just something simple like this?

let obj = [{ category: 'Residential', category_id: 1, types: [{ name: 'House', id: 1 }, { name: 'Townhouse / Villa', id: 3 }, { name: 'House and Land', id: 5 }, { name: 'Duplex', id: 4 }, { name: 'Land', id: 6 }, { name: 'Terrace', id: 16 }, { name: 'Apartment/Unit', id: 2 }, { name: 'Relocatable', id: 7 }] }, { category: 'Commercial', category_id: 2, types: [{ name: 'Office', id: 12 }, { name: 'House', id: 8 }, { name: 'Land', id: 9 }, { name: 'Shop', id: 10 }, { name: 'Factory', id: 11 }] }, { category: 'Rural', category_id: 3, types: [{ name: 'House', id: 17 }, { name: 'House and Land', id: 14 }, { name: 'Land', id: 13 }, { name: 'Terrace', id: 15 }] } ];

for (let elem of obj) {
  const typeFound = elem.types.find(type => type.id === 15);
  if (typeFound) {
      console.log(elem.category + " " + typeFound.name);
      break;
  }
}

Comments

0

Here's one way to do it. First, flatten the possible results to an array of results like [{id: 15, name: "Rural / Terrace"}, ...], then find the specific element you want.

let obj =[
    {
        category: 'Residential',
        category_id: 1,
        types: [{name: 'House', id: 1},{name: 'Townhouse / Villa', id: 3},{name: 'House and Land', id: 5},{name: 'Duplex', id: 4},{name: 'Land', id: 6},{name: 'Terrace', id: 16},{name: 'Apartment/Unit', id: 2},{name: 'Relocatable', id: 7}]
    },
    {
        category: 'Commercial',
        category_id: 2,
        types: [{name: 'Office', id: 12},{name: 'House', id: 8},{name: 'Land', id: 9},{name: 'Shop', id: 10},{name: 'Factory', id: 11}]
    },
    {
        category: 'Rural',
        category_id: 3,
        types: [{name: 'House', id: 17},{name: 'House and Land', id: 14},{name: 'Land', id: 13},{name: 'Terrace', id: 15}]
    }
];

const flatTypes = obj.map(cat =>
    cat.types.map(type => {
        return {
            id: type.id,
            name: `${cat.category} / ${type.name}`
        };
    })
).reduce((flatTypes, typeArray) =>
    flatTypes.concat(typeArray)
, []);

const result = flatTypes.find(type => type.id === 15).name;

console.log(result);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.