1

I am attempting to check if a one-dimensional array of objects contains specific values. I have an array of objects including people’s names and geographic locations. I am trying to check whether all continents are represented in the array.

I have tried to use a simple for loop to check through each element but it’s not working as intended.

My code:

function containsContinents(list, continents) {
  continents = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
  for (var i = 0; i < list.length; i++) {
    if ($.inArray(list[i], continents) == -1) {
      return false;
    }
  } return true;
} 

and the array of objects:

var list = [
  { firstName: 'Fatima', lastName: 'A.', country: 'Algeria', continent: 'Africa', age: 25, language: 'JavaScript' },
  { firstName: 'Agustín', lastName: 'M.', country: 'Chile', continent: 'Americas', age: 37, language: 'C' },
  { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' },
  { firstName: 'Laia', lastName: 'P.', country: 'Andorra', continent: 'Europe', age: 55, language: 'Ruby' },
  { firstName: 'Oliver', lastName: 'Q.', country: 'Australia', continent: 'Oceania', age: 65, language: 'PHP' },
];
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
MarcoM
  • 101
  • 1
  • 7
  • What if a `continent` occurs that isn’t included in the `continents` array, e.g. `{ firstName: "Augustus", lastName: "Le Plongeon",`…`continent: "Mu",`…`}`, even if all others do? Valid or not? – Sebastian Simon Sep 03 '21 at 11:35
  • Your algorithm checks to make sure that each continent is valid, but it makes no attempt to verify that all continents are seen in the list at least once. – Pointy Sep 03 '21 at 11:38

4 Answers4

3

This will check if all elements in you continent and list array match,It will return true if all your elements match.

   let continents = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];
    var list = [
      { firstName: 'Fatima', lastName: 'A.', country: 'Algeria', continent: 'Africa', age: 25, language: 'JavaScript' },
      { firstName: 'Agustín', lastName: 'M.', country: 'Chile', continent: 'Americas', age: 37, language: 'C' },
      { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' },
      { firstName: 'Laia', lastName: 'P.', country: 'Andorra', continent: 'Europe', age: 55, language: 'Ruby' },
      { firstName: 'Oliver', lastName: 'Q.', country: 'Australia', continent: 'Oceania', age: 65, language: 'PHP' },
    ];
    
    const found = continents.every((r) => typeof list.find( (a) => a.continent === r) !== 'undefined')

    
    console.log('a',found);
2

Try this:

var list = [
  {
    firstName: 'Fatima',
    lastName: 'A.',
    country: 'Algeria',
    continent: 'Africa',
    age: 25,
    language: 'JavaScript',
  },
  {
    firstName: 'Agustín',
    lastName: 'M.',
    country: 'Chile',
    continent: 'Americas',
    age: 37,
    language: 'C',
  },
  {
    firstName: 'Jing',
    lastName: 'X.',
    country: 'China',
    continent: 'Asia',
    age: 39,
    language: 'Ruby',
  },
  {
    firstName: 'Laia',
    lastName: 'P.',
    country: 'Andorra',
    continent: 'Europe',
    age: 55,
    language: 'Ruby',
  },
  {
    firstName: 'Oliver',
    lastName: 'Q.',
    country: 'Australia',
    continent: 'Oceania',
    age: 65,
    language: 'PHP',
  },
];

const continents = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];

const allContinentsAreThere = continents.every((continent) =>
  list.some((listItem) => listItem.continent === continent)
);

console.log(allContinentsAreThere);
Asen Mitrev
  • 633
  • 3
  • 10
2

In order to check if all continents are included at least once, you need to keep track of the continents you’ve found so far.

Since only the continent property is used, I’m going to simplify this array:

const list = [
  { continent: "Africa" },
  { continent: "Americas" },
  { continent: "Asia" },
  { continent: "Europe" },
  { continent: "Oceania" },
];

You’re also resetting the continents parameter to an array in the question post, rather than use what has been passed. The function call should look like containsContinents(list, [ "Africa", "Americas", "Asia", "Europe", "Oceania" ]) already, so setting the continents array inside the function is redundant.

Keeping track of found results is easy with Sets. You can obtain a Set of all used continents and all expected continents by mapping like this:

const usedContinents = new Set(list.map(({ continent }) => continent));
const expectedContinents = new Set(continents);

Now, you’re looking for a way to check if all expected continents occur in the used continents, but it’s not clear what is supposed to happen with used continents that are not included in the expected continents.

If your only criterion is “for all continents of the expected continents, the continent exists in the used continents”, then you have to check whether expectedContinents is a subset of usedContinents.

If an additional criterion is “the set of expected continents is the same as the set of used continents” (i.e. no used continent exists that doesn’t exist in the expected continents), then simply checking if the set sizes are the same is sufficient.

This function checks the subset relation using Array.from, every, and has:1

const isSubset = (a, b) => Array.from(a).every((elem) => b.has(elem));

The full code now looks like this:

const list = [
  { continent: "Africa" },
  { continent: "Americas" },
  { continent: "Asia" },
  { continent: "Europe" },
  { continent: "Oceania" }
];
const isSubset = (a, b) => Array.from(a).every((elem) => b.has(elem));
const allContinentsRepresented = (list, continents) => {
  const usedContinents = new Set(list.map(({ continent }) => continent));
  const expectedContinents = new Set(continents);

  return isSubset(expectedContinents, usedContinents);
  // Alternative:
  // return isSubset(expectedContinents, usedContinents) && expectedContinents.size === usedContinents.size;
};

console.log(allContinentsRepresented(list, [ "Africa", "Americas", "Asia", "Europe", "Oceania" ]));

If you want to exclude all unexpected continents, include the additional expectedContinents.size === usedContinents.size check. In that case, if the list contains an additional { continent: "Mu" }, but the passed continents array doesn’t, the allContinentsRepresented function will return false.

1: The New Set methods TC39 proposal will allow a simple a.isSubsetOf(b) or b.isSupersetOf(a) in the future.


Runtime complexity

Others have suggested to check continents.every((continent) => list.some((listItem) => listItem.continent === continent)). This has a quadratic runtime complexity (i.e. O(n²)), because the some has to perform a linear search through the array, but so does the every. Since some is called for each element, the time complexity is multiplied: O(n · n).

The approach with Sets is approximately linear (i.e. O(n)), as Sets use constant lookup time internally (like hash maps / hash tables). See also: Javascript ES6 computational/time complexity of collections. The every call performs a linear pass through the array, but the lookup with has requires approximately constant time.

Essentially, this means that the Set approach is more efficient.

(Note that Array.from, the two new Set calls, and the map call all perform a linear pass, but these calls are not nested; they’re not performed for every element within another linear pass, so the runtime complexity isn’t affected by all these calls.)

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
  • Great answer. You are right about runtime complexity getting out of hand when using .every(item => list.some()) – Asen Mitrev Sep 03 '21 at 12:25
0

To check all the continents is resent in the list

Logic

  • Loop through continents
  • Check if a node is present in list having continent from continents array.
  • If any node is not present, set the bool to false.

Working Fiddle

var list = [
  { firstName: 'Fatima', lastName: 'A.', country: 'Algeria', continent: 'Africa', age: 25, language: 'JavaScript' },
  { firstName: 'Agustín', lastName: 'M.', country: 'Chile', continent: 'Americas', age: 37, language: 'C' },
  { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' },
  { firstName: 'Laia', lastName: 'P.', country: 'Andorra', continent: 'Europe', age: 55, language: 'Ruby' },
  { firstName: 'Oliver', lastName: 'Q.', country: 'Australia', continent: 'Oceania', age: 65, language: 'PHP' },
];

const continents = ['Africa', 'Americas', 'Asia', 'Europe', 'Oceania'];

function containsContinents(list, continents) {
  let isAllContinentExist = true;
  continents.forEach((continent) => {
    isAllContinentExist = isAllContinentExist && list.find((node) => node.continent === continent) !== undefined;
  });
  return isAllContinentExist;
}
console.log(containsContinents(list, continents));
Nitheesh
  • 19,238
  • 3
  • 22
  • 49