Home > Software engineering >  Javascript, filtering on object in comparison to array
Javascript, filtering on object in comparison to array

Time:02-21

I'm still learning and I had a question the other day filtering two arrays, which helped a lot for my understanding!

However now, I have a new issue as the complexity has grown a bit from being two simple arrays! Now instead, I have a array with multiple objects named animals which categorizes animals based whether they are housepets, insects or wild animals and each contains a object with their characteristics. Now I want to compare this on a simple array seen below.

Array with Object

    let animals =  [
{
    "housePets" :  [ { "name": "Cat", "food" : "Fish", "description": "Long tail, sharp claws" },  { "name": "Dog", "food" : "Biscuits", "description" : "Humans best friend" } ]
},
{
    "wildAnimals" : [ { "name": "Giraffe", "food" : "Leafes", "description" : "A very long neck" }, { "name": "Lion", "food" : "Meat", "description" : "Featured in Lion King" } ]
  
},
{
        "insects" : [ { "name": "Ladybug", "food" : "Leafes", "description" : "Red and black" }, { "name": "Spider", "food" : "Flies", "description" : "From the friendly neighbourhood" } ]
      
    }]

Arr:

    let animalsArr2 = [housePets]

I'm having a bit of trouble fully understanding on how to work with this JSON format in general. The biggest struggle for me is targeting the specific array like wildAnimals.

For example, one thing I want to do is filter the animals array based on what's inside animalsArr2 and pick a random one from the animalsarr that's not featured in animalsArr2 like "wildAnimals" and "Insects". I hope someone can give me some ideas on how to tackle this issue or if it can be tackled in a easier way.

CodePudding user response:

You can use the .find() array method to return the list that you want. For example if you want to return the wild animals list:

let animals =  [
    {
        "housePets" : [
            { "name": "Cat", "food" : "Fish", "description": "Long tail, sharp claws" }, 
            { "name": "Dog", "food" : "Biscuits", "description" : "Humans best friend" }
        ]
    },
    {
        "wildAnimals" : [
            { "name": "Giraffe", "food" : "Leafes", "description" : "A very long neck" },
            { "name": "Lion", "food" : "Meat", "description" : "Featured in Lion King" }
        ]
      
    },
    {
        "insects" : [
            { "name": "Ladybug", "food" : "Leafes", "description" : "Red and black" },
            { "name": "Spider", "food" : "Flies", "description" : "From the friendly neighbourhood" }
        ]
    }
];

const wildAnimals = animals.find((item) => item.wildAnimals);

The code above basically checks which item in your array has a property called wildAnimals and returns that item. You can read more about this method Here.

Hope that helped!

CodePudding user response:

I'm gonna suppose you are forced to use this format of storing data, but I feel like I have to let you know that this isn't the best way to store info like this (you will see that it is hard to work with it). Instead of having an array of objects, you could have an object of arrays like this:

let animals = {
  "housePets": [{ "name": "Cat", "food": "Fish", "description": "Long tail, sharp claws" },  { "name": "Dog", "food": "Biscuits", "description": "Humans best friend" }],
  "wildAnimals": [{ "name": "Giraffe", "food": "Leafes", "description": "A very long neck" }, { "name": "Lion", "food": "Meat", "description": "Featured in Lion King" }]
}

With this approach, getting all house animals would be as easy as animals.housePets.
Back to your issue tho. If you want to get all house animals from this, you will have to filter the array. To filter arrays, you have to give it a condition that the element has to pass to be stored. Here you can see that only the object with the house animals has a housePets property, so we can take advantage of that:

let house_animals = animals.filter(obj => obj.housePets)[0].housePets; // [{ "name": "Cat", "food": "Fish", "description": "Long tail, sharp claws" },  { "name": "Dog", "food": "Biscuits", "description": "Humans best friend" }]

What it does is that it takes all the objects that have the "housePets" property, takes the first one (I suppose there will always be only one) and reads the property, giving you the array of animals.
To find animals that are only in the housePets section and not in others, you can do this:

let house_animals = animals.filter(obj => obj.housePets)[0].housePets;
let wild_animals = animals.filter(obj => obj.wildAnimals)[0].wildAnimals;
let insects = animals.filter(obj => obj.insects)[0].insects;
let only_house = house_animals.filter(animal => !wild_animals.includes(animal) && !insects.includes(animal); // This checks if the animal is in the wild_animals or insects array. If it isn't, it keeps it.

You can also check this question out
Hope this helped :)

CodePudding user response:

You can follow this code as a starting point. The complete example with updated data is below.

There are two key functions:

function _get(array, label): Take the array and get the names of the animals under the label category.

function _filterAndGet(mainList, filterList): Take the main list of animals, and filter out any animals that are in filter list. Then, pick a random animal from that filtered list.

Code

    const animals = [
    {
        housePets :  [{name: 'Cat', food : 'Fish', description: 'Long tail, sharp claws'}, {name: 'Dog', food : 'Biscuits', description : 'Humans best friend'}]
    },
    {
        wildAnimals : [{name: 'Giraffe', food : 'Leafes', description : 'A very long neck'}, {name: 'Lion', food : 'Meat', description : 'Featured in Lion King'}, {name: 'Cat', food : 'Fish', description: 'Long tail, sharp claws'}, {name: 'Ladybug', food : 'Leafes', description : 'Red and black'}]

    },
    {
        insects : [{name: 'Ladybug', food : 'Leafes', description : 'Red and black'}, {name: 'Spider', food : 'Flies', description : 'From the friendly neighbourhood'}]

    }]

const wildAnimals = _get(animals, 'wildAnimals');
console.log(`Wild animals: ${JSON.stringify(wildAnimals)}`);

const housePetsAndInsects = _get(animals, 'housePets').concat(_get(animals, 'insects'));
console.log(`House Pets and Insects: ${housePetsAndInsects}`);

console.log(`Random wild animal not in housePets and insects: ${_filterAndGet(wildAnimals, housePetsAndInsects)}`);

function _filterAndGet(mainList, filterList) {
    const filterSet = new Set(filterList);
    const filteredMainList = mainList.filter(e => !filterSet.has(e));
    const index = Math.floor(Math.random() * filteredMainList.length);
    return filteredMainList[index];
}

function _get(array, label) {
    const res = [];
    for (const elem of array) {
        for (const objKey of Object.keys(elem)) {
            if (objKey === label) {
                for (const item of elem[objKey]) {
                    res.push(item.name);
                }
                return res;
            }
        }
    }
    return res;
}

Example output:

Wild animals: ["Giraffe","Lion","Cat","Ladybug"]
House Pets and Insects: Cat,Dog,Ladybug,Spider
Random wild animal not in housePets and insects: Lion
  • Related