3

I have js object like this

var continents = [
0: {
       short: 'na',
       countries: [
           {
               name: 'canada'
           },
           {
               name: 'usa'
           },
           //...
       ]

   },
   1: {
       short: 'sa',
       countries: [
           {
               name: 'chile'
           },
           {
               name: 'colombia'
           }
       ]

     },
//...
]

I want to filter this object for matches with country name (contents.countries.name) with some string (example 'col') Example filter function

filter(item => {
    return item.name.toLowerCase().indexOf('col'.toLowerCase()) >= 0;
});

Expecting result:

  1: {
       short: 'sa',
       countries: [
           {
               name: 'colombia'
           }
       ]
     }
0

5 Answers 5

1

You need to not only filter on the continents, but the countries within them.

This is a two-part filter, as seen below.

var continents = [{
  short: 'na',
  countries: [
    { name: 'canada' },
    { name: 'usa' }
  ]
}, {
  short: 'sa',
  countries: [
    { name: 'chile' },
    { name: 'colombia' }
  ]
}];

function filterByKeyValue(arr, keys, val) {
  return arr.filter(item => {
    return item[keys[0]].some(subitem => subitem[keys[1]].indexOf(val) > -1);
  }).map(item => {
    item[keys[0]] = item[keys[0]].filter(subitem => subitem[keys[1]].indexOf(val) > -1);
    return item;
  });
}

var filtered = filterByKeyValue(continents, [ 'countries', 'name' ], 'col');

console.log(filtered);
.as-console-wrapper { top: 0; max-height: 100% !important; }
<!--

Original filter that method is based on.

var filtered = continents.filter(continent => {
  return continent.countries.some(country => country.name.indexOf('col') > -1);
}).map(continent => {
  continent.countries = continent.countries.filter(country => country.name.indexOf('col') > -1);
  return continent;
});

-->

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

Comments

0

item in this case has two properties, countries and short. You are trying to run .name on item, which doesn't exist. You need to run .name on either item.countries[0].name or item.countries[1].name.

    var continents = [
        {
            short: 'na',
            countries: [
                {
                    name: 'canada'
                },
                {
                    name: 'usa'
                }
            ]

        },
        {
            short: 'sa',
            countries: [
                {
                    name: 'chile'
                },
                {
                    name: 'colombia'
                }
            ]

        }
    ];

    var results = continents.filter(item => {
        return item.countries[0].name.toLowerCase().indexOf('col'.toLowerCase()) >= 0 || 
item.countries[1].name.toLowerCase().indexOf('col'.toLowerCase()) >= 0
    });

    console.log(results);

Working example: https://jsfiddle.net/gugui3z24/fnw5kf0x/

1 Comment

Yes. I have 6 continents and over 250 countries inside them. i look for the solution how to loop through them and filter
0

You can use the filter function to return just the items that match a condition. Like so:

const matches = [];
continents.forEach((continent) => {

  const countries = continent.countries.filter((country) => {
    return country.name.includes('col');
  });

  matches.push(...countries);
});

Note: I have used the spread operator ... to flattern the array (avoiding an array of arrays).

Comments

0

For a loop you could use:

var continents = [
    {
        short: 'na',
        countries: [
            {
                name: 'canada'
            },
            {
                name: 'usa'
            }
        ]
    },
    {
        short: 'sa',
        countries: [
            {
                name: 'chile'
            },
            {
                name: 'colombia'
            }
        ]
    }
];

var results = continents.filter(item => {
    for (let x = 0; x < item.countries.length; x++) {
        if (item.countries[x].name.toLowerCase().indexOf('usa') > -1) {
            return item;
            break;
        }
    }
});

console.log(results);

Working example: https://jsfiddle.net/gugui3z24/fnw5kf0x/2/

Comments

0

You could try to filter the countries and if one found, push the outer continent as well to the result set.

function getItems(name) {
    var result = [];

    continents.forEach(function (continent) {
        var countries = continent.countries.filter(function (country) {
            return country.name.startsWith(name);
        });
        if (countries.length) {
            result.push({ short: continent.short, countries: countries });
        }
    });
    return result;
}

var continents = [{ short: 'na', countries: [{ name: 'canada' }, { name: 'usa' }] }, { short: 'sa', countries: [{ name: 'chile' }, { name: 'colombia' }] }];

console.log(getItems('col'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.