1

I was given a task, and I must be missing something. The provided code isn't the original question but similar. I have to count how many people in the array are aged 16 or over. I have played around with it and I can't work it out. Please, can someone explain what I am doing wrong?

In the task, I am given an array of objects:

var people = [{name:'Emma', age:15},{name:'Matt', age: 16}, {name:'Janet', age:17}]

I need to complete a function to count how many people are aged 16 or over. The start of the function is given (i.e. function correctAge(people){ //Complete })

The 'Example Code' is some skeleton code I have been playing around with. The 'Incorrect Attempt' is my attempt which is the code I keep coming back to or a variation of which is also correct...

Please Help

Incorrect attempt:

var people = [
  {name: "Emma", age: 15},
  {name: "Matt", age: 16},
  {name: "Tom", age: 17}
];

function correctAge(array) {
  // Complete the function to return how many people are age 16+
  var count = 0;

  for (let i = 0; i < array.length; i++) {
    var obj = array.length[i];
    for (prop in obj) {
      if (prop[obj] >= 16) {
        count++;
      }
    }
    return count;
  }
}

console.log(correctAge(people));

Example code:

var people = [
  {name: "Emma", age: 15},
  {name: "Matt", age: 16},
  {name: "Tom", age: 17}
];

function correctAge(people) {
  // Complete the function to return how many people are age 16+
}
BCDeWitt
  • 4,540
  • 2
  • 21
  • 34
Ewal90
  • 11
  • 4
  • 2
    please add the code and attempt as text to the question. – Nina Scholz Sep 19 '19 at 06:43
  • You shouldn't loop over all the properties in the object, you should just use `obj.age` – Barmar Sep 19 '19 at 06:47
  • Post your code as plain text, not images. You can use [Stack Snippets](https://meta.stackoverflow.com/questions/358992/ive-been-told-to-create-a-runnable-example-with-stack-snippets-how-do-i-do) to create an executable example. – Barmar Sep 19 '19 at 06:48

8 Answers8

0

You need to take the object by using the index.

obj = array[i];

Then you can take the property directly without looping all properties.

if (obj.age >= 16) {
    count++;
}

You could put both parts into a single check, without using another variable obj.

if (array[i].age >= 16) {
    count++;
}

.age is a property accessor of the object.

{
    name: 'Emma',
    age: 15       // <--
}

If you like a single line approach, you could reduce the array and count the occurences.

return array.reduce((count, { age }) => count + (age >= 16), 0);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

It would be much simpler to use the array's filter method:

function correctAge(people = [], age = 16){

    return people.filter( person => person.age > age ).length
}
Slim
  • 1,924
  • 1
  • 11
  • 20
  • Thanks. This is great, and works for me. No idea why I am trying to make this so complicated. – Ewal90 Sep 19 '19 at 07:01
0
people.filter(x=>{return x.age>=16}).length;

Add above line of code into your function.

Sudhakar
  • 533
  • 1
  • 3
  • 17
0

Iterate over your array, check property of element matches parameter and increment a counter.

Code example below, names and properties have been changed to protect the innocent.

const cars = [
  { make: 'Nissan', country: 'Japan' },
  { make: 'Ford', country: 'USA' },
  { make: 'Chevy', country: 'USA' },
  { make: 'Volvo', country: 'Sweden' },
  { make: 'Mitsubishi', country: 'Japan' },
];

function fromCountry(cars, country) {
  let count = 0;
  for(let i = 0; i < cars.length; i++) {
    if (cars[i].country === country) {
      count++;
    }
  }
  return count;
}

const fromCountry2 = (cars, country) => cars.reduce((count, car) => {
  car.country === country && count++;
  return count;
}, 0);

console.log(fromCountry(cars, 'Japan')); // 2
console.log(fromCountry(cars, 'Sweden')); // 1
console.log(fromCountry(cars, 'USA')); // 2
console.log(fromCountry(cars, 'Canada')); // 0

console.log(fromCountry2(cars, 'Japan')); // 2
console.log(fromCountry2(cars, 'Sweden')); // 1
console.log(fromCountry2(cars, 'USA')); // 2
console.log(fromCountry2(cars, 'Canada')); // 0
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
0

Try this you will get your result;

var people = [{name:'Emma', age:15},{name:'Matt', age: 16}, {name:'Janet', age:17}];

const correctAge = function(age) {
 return people.filter(x => x.age < age).length;
}

console.log(correctAge(16));
Arsalan Akhtar
  • 395
  • 2
  • 15
0

Array.reduce() is an elegant solution to this -

function correctAge(array) {
  return array.reduce((total, person) => {
      return person.age >= 16 ? ++total : total;
    }, 0)
}

For the example in the question, this returns the value 2.

Nithin Kumar Biliya
  • 2,763
  • 3
  • 34
  • 54
0

Most of the answers here focus on the use of Array.filter() or Array.reduce() (which I believe is the most appropriate approach). But, I would like to point out how to modify your "incorrect attempt" to make it actually work. Here are some steps I took to correct it:

  1. Remove the prop loop. You only care about the age property here, so there is no need to check the other props. (prop[obj] is actually backwards, anyway. It should be obj[prop])
  2. Move return count; outside the outer for loop.
  3. Replace array.length[i] with array[i]. The .length array property is an integer, not an array or object.

var people = [
  {name: "Emma", age: 15},
  {name: "Matt", age: 16},
  {name: "Tom", age: 17}
];

function correctAge(people) {
  // Complete the function to return how many people are age 16+
  var count = 0;

  for (let i = 0; i < people.length; i++) {
    var obj = people[i]; // <-- instead of array.length[i]
    if (obj.age >= 16) { // <-- obj.age instead of obj[prop]
      count++;
    }
  }
  return count; // <-- moved outside the loop
}

console.log(correctAge(people));

Now, again, but using Array.reduce(), which is a great tool for aggregation:

var people = [
  {name: "Emma", age: 15},
  {name: "Matt", age: 16},
  {name: "Tom", age: 17}
];

function correctAge(people) {
  // start at 0, then add 1 when obj.age >= 16, 0 otherwise
  return people.reduce(
    (acc, obj) => acc + (obj.age >= 16 ? 1 : 0), 0
  );
}

console.log(correctAge(people));

Array.filter() is the most readable method, imo:

var people = [
  {name: "Emma", age: 15},
  {name: "Matt", age: 16},
  {name: "Tom", age: 17}
];

function correctAge(people) {
  return people.filter(obj => obj.age >= 16).length;
}

console.log(correctAge(people));

...and, finally, a few more suggestions, which may not meet your current criteria, but are important to know for the sake of readability/maintainability in your future endeavors (especially for larger code bases):

  1. I see you're using let in your example, which means you have access to const. I would encourage you to use const instead of let as much as possible. Also, because const and let work differently than var (block-scoping), I would stop using var entirely, to avoid confusion. const can also be used on functions to prevent them from ever being replaced.
  2. Following a consistent coding style also helps with readability over time. In case you don't know about them, style guides like Standard or Airbnb are particularly helpful because they point to reasoning and additional tools you can use to enforce those rules. (My perspective on const originally came from Airbnb, for example)
  3. As encouraged in the Functional Programming paradigm, immutability is also important. Even if we don't have access to immutables in JS (without the help of libraries or Object.freeze(), at least), simply treating values as immutable, as a habit, has the same benefits - and const often gets you halfway there by preventing re-assignment.
  4. Naming is hard, but worth the effort. For example, person would be more descriptive than obj. Also correctAge isn't descriptive enough on its own - you don't know what the "correct age" is without finding the function and looking at its definition. This isn't a problem for this example because it's small but, like the rest of these suggestions, it's best to build up good habits on smaller examples like this so you don't need to think about it later.
  5. When using array/iterable methods, I think it's better to define the callback rather than an array wrapper. This keeps the functions more composable - that is, you can easily mix/match them.

...which leads to my final snippet:

const people = [
  {name: 'Matt', age: 15},
  {name: 'Emma', age: 15},
  {name: 'Matt', age: 16},
  {name: 'Tom', age: 17},
  {name: 'Matt', age: 37}
]

const personHasName = (person, name) => person.name === name
const personIsOfAge = (person, age) => person.age >= age

// Composition of personHasName and personIsOfAge
const mattsOver16 = person =>
    personHasName(person, 'Matt') && personIsOfAge(person, 16)

console.log(
  people.filter(mattsOver16).length
)
BCDeWitt
  • 4,540
  • 2
  • 21
  • 34
-2
let count = 0;
function isGreater(val) {
    if (val.age > 16) count++;
}
people.filter((val) => isGreater(val));
asportnoy
  • 2,218
  • 2
  • 17
  • 31
nikita shinde
  • 47
  • 1
  • 1
  • Please don't post code-only answers to old questions. If you feel your answer is worthy, *explain* what makes it better, and how it works. Also, please view [the article on how to format code](/help/formatting). – Heretic Monkey Jun 16 '23 at 13:27