Working With Arrays
Section content
Simple Array Methods
The new at() method
Looping Arrays: forEach()
forEach() with Maps and Sets
Data Transformations: map() , filter() and reduce() methods
Chaining of Methods
The find() method
The findIndex() method
some() and every()
flat() and flatMap()
Sorting Arrays
More Ways of Creating and Filling Arrays
Theories
'use strict';

/* SIMPLE ARRAY METHODS ==================================================

    slice(), splice(), reverse(), concat(), join()

*/

let arrOne = ['a', 'b', 'c', 'd', 'e'];

// SLICE -> DOESN'T MUTATES the original array
console.log(arrOne.slice(2)); // ▶ (3) ['c', 'd', 'e']
console.log(arrOne.slice(2, 4)); // ▶ (2) ['c', 'd']
console.log(arrOne.slice(-2)); // ▶ (2) ['d', 'e']
console.log(arrOne.slice(-1)); // ▶ ['e']
console.log(arrOne.slice(1, -2)); // ▶ (2) ['b', 'c']
console.log(arrOne.slice()); // ▶ (5) ['a', 'b', 'c', 'd', 'e'] -> sallow copy
console.log([...arrOne]); // ▶ (5) ['a', 'b', 'c', 'd', 'e'] -> sallow copy

// SPLICE -> MUTATES the original array
arrOne.splice(-1);
console.log(arrOne); // ▶ (4) ['a', 'b', 'c', 'd']
arrOne.splice(1, 2);
console.log(arrOne); // ▶ (2) ['a', 'd']

// REVERSE -> MUTATES the original array
arrOne = ['a', 'b', 'c', 'd', 'e'];
const arrTwo = ['j', 'i', 'h', 'g', 'f'];
console.log(arrTwo.reverse()); // ▶ (5) ['f', 'g', 'h', 'i', 'j']
console.log(arrTwo); // ▶ (5) ['f', 'g', 'h', 'i', 'j']

// CONCAT -> DOESN'T MUTATES any of the involved arrays
const letters = arrOne.concat(arrTwo);
console.log(letters); // ▶ (10) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
console.log([...arrOne, ...arrTwo]); // ▶ (10) ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']

// JOIN -> DOESN'T MUTATES any of the involved arrays
console.log(letters.join(' - ')); // a - b - c - d - e - f - g - h - i - j

/* THE NEW AT() METHOD ==================================================

    Introduced on ES2020

*/
const arr = [23, 11, 64];
console.log(arr[0]); // 23
console.log(arr.at(0)); // 23

// getting last array element
console.log(arr[arr.length - 1]); // 64
console.log(arr.slice(-1)[0]); // 64
console.log(arr.at(-1)); // 64

console.log('jonas'.at(0)); // j
console.log('jonas'.at(-1)); // s

/* LOOPING ARRAYS: forEach() ==================================================

    Can not use 'continue' and 'break' keywords in forEach loop

*/

const movements = [200, 450, -400, 3000, -650, -130, 70, 1300];

// for-of loop
for (const [i, movement] of movements.entries()) {
  if (movement > 0) {
    console.log(`Movement ${i + 1}: You deposited ${movement}`);
  } else {
    console.log(`Movement ${i + 1}: You withdrew ${Math.abs(movement)}`);
  }
}

// forEach loop
console.log('––––– FOREACH –––––');
movements.forEach(function (mov, i, arr) {
  if (mov > 0) {
    console.log(`Movement ${i + 1}: You deposited ${mov}`);
  } else {
    console.log(`Movement ${i + 1}: You withdrew ${Math.abs(mov)}`);
  }
  // console.log(arr);
});

/* forEach() WITH MAPS AND SETS ==================================================

*/

// Map
const currencies = new Map([
  ['USD', 'United States dollar'],
  ['EUR', 'Euro'],
  ['GBP', 'Pound sterling'],
]);

currencies.forEach(function (value, key, map) {
  console.log(`${key}: ${value}`);
  console.log(map);
});

// Set
const currenciesUnique = new Set(['USD', 'GBP', 'USD', 'EUR', 'EUR']);

currenciesUnique.forEach(function (value, _, set) {
  console.log(`${value}: ${value}`);
  console.log(set);
});

/* DATA TRANSFORMATIONS: map(), filter() AND reduce() METHODS ==================================================

  💠 map() returns a new array containing the results of applying an operation on all original array elements

  💠 filter() returns a new array containing the array elements that passed a specified test condition

  💠 reduce() boils (“reduces”) all array elements down to one single value (e.g. adding all elements together)

  All map(), filter(), and reduce() don't mutate the original array.

*/

// ––– The map() method –––
const eurToUsd = 1.1;

// const movementsUSD = movements.map(function (mov) {
//   return mov * eurToUsd;
// });

const movementsUSD = movements.map(mov => mov * eurToUsd);

console.log(movements);
console.log(movementsUSD);

const movementsUSDfor = [];
for (const mov of movements) movementsUSDfor.push(mov * eurToUsd);
console.log(movementsUSDfor);

const movementsDescriptions = movements.map(
  (mov, i) => `Movement ${i + 1}: You ${mov > 0 ? 'deposited' : 'withdrew'} ${Math.abs(mov)}`
);
console.log(movementsDescriptions);

// ––– The filter() method –––
const deposits = movements.filter(function (mov, i, arr) {
  return mov > 0;
});
console.log(movements);
console.log(deposits);

const depositsFor = [];
for (const mov of movements) if (mov > 0) depositsFor.push(mov);
console.log(depositsFor);

const withdrawals = movements.filter(mov => mov < 0);
console.log(withdrawals);

// ––– The reduce() method –––
console.log(movements);

// accumulator -> SNOWBALL
// const balance = movements.reduce(function (acc, cur, i, arr) {
//   console.log(`Iteration ${i}: ${acc}`);
//   return acc + cur;
// }, 0);
const balance = movements.reduce((acc, cur) => acc + cur, 1);
console.log(balance);

let balance2 = 0;
for (const mov of movements) balance2 += mov;
console.log(balance2);

// Maximum value
const max = movements.reduce(
  (acc, mov) => { if (acc > mov) return acc; else return mov; }, movements[0]
);
console.log(max);

/* CHAINING OF METHODS ==================================================

    💠 We should use chaining sparingly because chaining many methods can cause performance issues if we have massive arrays. So if we have many chaining methods, chained one after the other, we should compress all the functionality they do into as few methods as possible.

    💠 Don't use chaining with methods that mutate the original array. For example: splice(), reverse()

*/

// THE CHAINING <-> PIPELINE
const totalDepositsUSD = movements
  .filter(mov => mov > 0)
  .map(mov => mov * eurToUsd)
  .reduce((acc, mov) => acc + mov, 0);

console.log(totalDepositsUSD);

/* THE find() METHOD ==================================================

    The find() method of Array instances returns the first element in the provided array that satisfies the testing function. If no values satisfy the testing function, undefined is returned.

*/

const account1 = {
  owner: 'Jonas Schmedtmann',
  movements: [200, 450, -400, 3000, -650, -130, 70, 1300],
  interestRate: 1.2, // %
  pin: 1111,
};

const account2 = {
  owner: 'Jessica Davis',
  movements: [5000, 3400, -150, -790, -3210, -1000, 8500, -30],
  interestRate: 1.5,
  pin: 2222,
};

const account3 = {
  owner: 'Steven Thomas Williams',
  movements: [200, -200, 340, -300, -20, 50, 400, -460],
  interestRate: 0.7,
  pin: 3333,
};

const account4 = {
  owner: 'Sarah Smith',
  movements: [430, 1000, 700, 50, 90],
  interestRate: 1,
  pin: 4444,
};

const accounts = [account1, account2, account3, account4];

const firstWithdrawal = movements.find(mov => mov < 0);
console.log(firstWithdrawal);

const account = accounts.find(acc => acc.owner === 'Jessica Davis');
console.log(account);

/* THE findIndex() METHOD ==================================================

    The findIndex() method of Array instances returns the index of the first element in an array that satisfies the provided testing function. If no elements satisfy the testing function, -1 is returned.

*/

const index = accounts.findIndex(acc => acc.owner === 'Sarah Smith');
const indexTung = accounts.findIndex(acc => acc.owner === 'Tung');
console.log(index, indexTung); // 3 -1

/* some() AND every() ==================================================

    The some() method of Array instances tests whether at least one element in the array passes the test implemented by the provided function. It returns true if, in the array, it finds an element for which the provided function returns true; otherwise, it returns false. It doesn't modify the array.

    The every() method of Array instances tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value.
*/

// EQUALITY
console.log(movements.includes(-130)); // true

// SOME: CONDITION
console.log(movements.some(mov => mov === -130)); // true

const anyDeposits = movements.some(mov => mov > 0);
console.log(anyDeposits); // true

// EVERY
console.log(movements.every(mov => mov > 0)); // false
console.log(account4.movements.every(mov => mov > 0)); // true

// Separate callback
const deposit = mov => mov > 0;
console.log(movements.some(deposit)); // true
console.log(movements.every(deposit)); // false
console.log(movements.filter(deposit)); // ▶ (5) [200, 450, 3000, 70, 1300]

/* flat() AND flatMap() ==================================================

    Introduced on ES2019

    The flat() method of Array instances creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.

    The flatMap() method of Array instances returns a new array formed by applying a given callback function to each array element and then flattening the result by ONE LEVEL. It is identical to a map() followed by a flat() of depth 1 (arr.map(...args).flat()), but slightly more efficient than calling those two methods separately.

*/

const arrNum = [[1, 2, 3], [4, 5, 6], 7, 8];
console.log(arrNum.flat()); // ▶ (8) [1, 2, 3, 4, 5, 6, 7, 8]

const arrDeep = [[[1, 2], 3], [4, [5, 6]], 7, 8];
console.log(arrDeep.flat(1)); // ▶ (6) [[1, 2], 3, 4, [5, 6], 7, 8]
console.log(arrDeep.flat(2)); // ▶ (8) [1, 2, 3, 4, 5, 6, 7, 8]

const arrSoDeep = [0, 1, [2, [3, [4, [5, [6, 7, [8]]]]]]];
console.log(arrSoDeep.flat(Infinity)); // ▶ (8) [1, 2, 3, 4, 5, 6, 7, 8]

// flat
const overallBalance = accounts
  .map(acc => acc.movements)
  .flat()
  .reduce((acc, mov) => acc + mov, 0);
console.log(overallBalance);

// flatMap -> flattening the result by ONE LEVEL
const overallBalance2 = accounts
  .flatMap(acc => acc.movements)
  .reduce((acc, mov) => acc + mov, 0);
console.log(overallBalance2);

/* SORTING ARRAYS ==================================================

    The sort() method of Array instances sorts the elements of an array in place and returns the reference to the same array, which is now sorted. The default sort order is ascending, built upon converting the elements into strings and comparing their UTF-16 code unit value sequences.

    The sort() method does mutate the original array. To sort the elements in an array without mutating the original array, use toSorted().

    Syntax:
      sort() -> covert to string and sorting
      sort(compareFn) -> resultOfCompareFn(a, b) < 0 => a, b
      sort(compareFn) -> resultOfCompareFn(a, b) > 0 => b, a

    Ascending order: (a, b) => a - b
    Descending order: (a, b) => b - a

*/

// Strings
const owners = ['Jonas', 'Zach', 'Adam', 'Martha'];
console.log(owners.sort()); // ▶ (4) ['Adam', 'Jonas', 'Martha', 'Zach']
console.log(owners); // ▶ (4) ['Adam', 'Jonas', 'Martha', 'Zach']

// Numbers
console.log(movements);

// return < 0 => A, B (keep order)
// return > 0 => B, A (switch order)

// Ascending
// movements.sort((a, b) => {
//   if (a > b) return 1;
//   if (a < b) return -1;
// });
movements.sort((a, b) => a - b);
console.log(movements);

// Descending
// movements.sort((a, b) => {
//   if (a > b) return -1;
//   if (a < b) return 1;
// });
movements.sort((a, b) => b - a);
console.log(movements);

/* MORE WAYS OF CREATING AND FILLING ARRAYS ==================================================

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Array

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from
*/

const arrNumber = [1, 2, 3, 4, 5, 6, 7]; // ▶ (7) [1, 2, 3, 4, 5, 6, 7]
console.log(new Array(1, 2, 3, 4, 5, 6, 7)); // ▶ (7) [1, 2, 3, 4, 5, 6, 7]

// Empty arrays + fill method
const x = new Array(7);
console.log(x); // ▶ (7) [empty × 7]
x.fill(1, 3, 5);
console.log(x); // ▶ (7) [empty × 3, 1, 1, empty × 2]

arr.fill(23, 2, 6);
console.log(arr); // ▶ (3) [23, 11, 23]

// Array.from
const y = Array.from({ length: 7 }, () => 1);
console.log(y); // ▶ (7) [1, 1, 1, 1, 1, 1, 1]

const z = Array.from({ length: 7 }, (_, i) => i + 1);
console.log(z); // (7) [1, 2, 3, 4, 5, 6, 7]

const diceArr = Array.from({ length: 100 }, () => Math.trunc(Math.random() * 6 + 1));
console.log('Arrays of 100 rolls of dice:\n', diceArr);

const diceRolls = Array.from({ length: 100 }, () => {
  let roll = 0;
  do roll = Math.trunc(Math.random() * 6 + 1); while (roll === 1);
  return roll;
});
console.log('Arrays of 100 rolls of dice without 1:\n', diceRolls);

const items = document.querySelectorAll('.item');
const itemArrays = Array.from(items, item => item.innerText.replaceAll('\n', ' ').replaceAll(' ,', ','));
console.log('Section content:\n', itemArrays);

/* WHICH ARRAY METHOD TO USE? 🤔 ==================================================

    💠 To mutate original array
      👉 Add to original: .push() – end, .unshift() – start
      👉 Remove from original: .pop() – end, .shift() – start, .splice() – any
      👉 Others: reverse(), sort(), fill()

    💠 A new array
      👉 Computed from original: .map() – loop
      👉 Filtered using condition: .filter()
      👉 Portion of original: .slice()
      👉 Adding original to other: .concat()
      👉 Flattening the original: .flat(), .flatMap()

    💠 An array index
      👉 Based on value: .indexOf()
      👉 Based on test condition: .findIndex()

    💠 An array element
      👉 Based on test condition: .find()

    💠 Know if array includes
      👉 Based on value: .includes()
      👉 Based on test condition: .some(), .every()

    💠 A new string
      👉 Based on separator string: .join()

    💠 To transform to value
      👉 Based on accumulator: .reduce() – (Boil down array to single value of any type: number, string, boolean, or even new array or object)

    💠 To just loop array
      👉 Based on callback: .forEach() – (Does not create a new array, just loops over it)

*/

/* ARRAY METHODS PRACTICE ==================================================
*/

// 1.
const bankDepositSum = accounts
  .flatMap(acc => acc.movements)
  .filter(mov => mov > 0)
  .reduce((sum, cur) => sum + cur, 0);

console.log(bankDepositSum); // 25180

// 2.
// const numDeposits1000 = accounts
//   .flatMap(acc => acc.movements)
//   .filter(mov => mov >= 1000).length;

const numDeposits1000 = accounts
  .flatMap(acc => acc.movements)
  .reduce((count, cur) => (cur >= 1000 ? ++count : count), 0);

console.log(numDeposits1000); // 6

// Prefixed ++ operator
let a = 10;
console.log(++a); // 11
console.log(a); // 11

// 3.
const { deposits: accDeposits, withdrawals: accWithdrawals } = accounts
  .flatMap(acc => acc.movements)
  .reduce(
    (sums, cur) => {
      // cur > 0 ? (sums.deposits += cur) : (sums.withdrawals += cur);
      sums[cur > 0 ? 'deposits' : 'withdrawals'] += cur;
      return sums;
    },
    { deposits: 0, withdrawals: 0 }
  );

console.log(accDeposits, accWithdrawals); // 25180 -7340

// 4.
// this is a nice title -> This Is a Nice Title
const convertTitleCase = function (title) {
  // const capitalize = str => str[0].toUpperCase() + str.slice(1);
  const capitalize = str => str.replace(str[0], str[0].toUpperCase());

  const exceptions = ['a', 'an', 'and', 'the', 'but', 'or', 'on', 'in', 'with'];

  const titleCase = title
    .toLowerCase()
    .split(' ')
    .map(word => (exceptions.includes(word) ? word : capitalize(word)))
    .join(' ');

  return capitalize(titleCase);
};

console.log(convertTitleCase('this is a nice title')); // This Is a Nice Title
console.log(convertTitleCase('this is a LONG title but not too long')); // This Is a Long Title but Not Too Long
console.log(convertTitleCase('and here is another title with an EXAMPLE')); // And Here Is Another Title with an Example
JavaScript
Coding exercises
'use strict';

/* CODING CHALLENGE #1 ==================================================

    Julia and Kate are doing a study on dogs. So each of them asked 5 dog owners about their dog's age, and stored the data into an array (one array for each). For now, they are just interested in knowing whether a dog is an adult or a puppy. A dog is an adult if it is at least 3 years old, and it's a puppy if it's less than 3 years old.

    YOUR TASKS:

    Create a function 'checkDogs', which accepts 2 arrays of dog's ages ('dogsJulia' and 'dogsKate'), and does the following things:

    1. Julia found out that the owners of the FIRST and the LAST TWO dogs actually have cats, not dogs! So create a shallow copy of Julia's array, and remove the cat ages from that copied array (because it's a bad practice to mutate function parameters)

    2. Create an array with both Julia's (corrected) and Kate's data

    3. For each remaining dog, log to the console whether it's an adult ("Dog number 1 is an adult, and is 5 years old") or a puppy ("Dog number 2 is still a puppy 🐶")

    4. Run the function for both test datasets

    HINT: Use tools from all lectures in this section so far 😉

    TEST DATA 1: Julia's data [3, 5, 2, 12, 7], Kate's data [4, 1, 15, 8, 3]
    TEST DATA 2: Julia's data [9, 16, 6, 8, 3], Kate's data [10, 5, 6, 1, 4]

*/

const juliaOne = [3, 5, 2, 12, 7];
const kateOne = [4, 1, 15, 8, 3];
const juliaTwo = [9, 16, 6, 8, 3];
const kateTwo = [10, 5, 6, 1, 4];

const checkDogs = function (dogsJulia, dogsKate) {
  const dogsOfJulia = dogsJulia.slice();
  dogsOfJulia.splice(0, 1);
  dogsOfJulia.splice(-2);

  const dogs = dogsOfJulia.concat(dogsKate);

  dogs.forEach((age, i) => {
    if (age >= 3) {
      console.log(`Dog number ${i + 1} is an adult, and it is ${age} years old.`);
    } else {
      console.log(`Dog number ${i + 1} is still a puppy 🐶.`);
    }
  })
}

checkDogs(juliaOne, kateOne);
checkDogs(juliaTwo, kateTwo);

/* CODING CHALLENGE #2 ==================================================

    Let's go back to Julia and Kate's study about dogs. This time, they want to convert dog ages to human ages and calculate the average age of the dogs in their study.

    YOUR TASKS:

    Create a function 'calcAverageHumanAge', which accepts an arrays of dog's ages ('ages'), and does the following things in order:

    1. Calculate the dog age in human years using the following formula: if the dog is <= 2 years old, humanAge = 2 * dogAge. If the dog is > 2 years old, humanAge = 16 + dogAge * 4.

    2. Exclude all dogs that are less than 18 human years old (which is the same as keeping dogs that are at least 18 years old)

    3. Calculate the average human age of all adult dogs (you should already know from other challenges how we calculate averages 😉)

    4. Run the function for both test datasets

    TEST DATA 1: [5, 2, 4, 1, 15, 8, 3]
    TEST DATA 2: [16, 6, 10, 5, 6, 1, 4]

*/

const agesOne = [5, 2, 4, 1, 15, 8, 3];
const agesTwo = [16, 6, 10, 5, 6, 1, 4];

const calcAverageHumanAge = function (ages) {
  const humanAges = ages.map(age => age <= 2 ? age * 2 : 16 + age * 4);
  const adultDogs = humanAges.filter(age => age >= 18);
  return adultDogs.reduce((acc, age, _, arr) => acc + age / arr.length, 0);
}

/* CODING CHALLENGE #3 ==================================================

    Rewrite the 'calcAverageHumanAge' function from the previous challenge, but this time as an arrow function, and using chaining!

*/

const averageHumanAge = ages =>
  ages
    .map(age => age <= 2 ? age * 2 : 16 + age * 4)
    .filter(age => age >= 18)
    .reduce((acc, age, _, arr) => acc + age / arr.length, 0);

const avgOne = averageHumanAge(agesOne); console.log(avgOne);
const avgTwo = averageHumanAge(agesTwo); console.log(avgTwo);

/* CODING CHALLENGE #4 ==================================================

    Julia and Kate are still studying dogs, and this time they are studying if dogs are eating too much or too little.

    Eating too much means the dog's current food portion is larger than the recommended portion, and eating too little is the opposite.

    Eating an okay amount means the dog's current food portion is within a range 10% above and 10% below the recommended portion (see hint).

    YOUR TASKS:

      1. Loop over the array containing dog objects, and for each dog, calculate the recommended food portion and add it to the object as a new property. Do NOT create a new array, simply loop over the array. Formula: recommendedFood = weight ** 0.75 * 28. (The result is in grams of food, and the weight needs to be in kg)

      2. Find Sarah's dog and log to the console whether it's eating too much or too little. HINT: Some dogs have multiple owners, so you first need to find Sarah in the owners array, and so this one is a bit tricky (on purpose) 🤓

      3. Create an array containing all owners of dogs who eat too much ('ownersEatTooMuch') and an array with all owners of dogs who eat too little ('ownersEatTooLittle').

      4. Log a string to the console for each array created in 3., like this: "Matilda and Alice and Bob's dogs eat too much!" and "Sarah and John and Michael's dogs eat too little!"

      5. Log to the console whether there is any dog eating EXACTLY the amount of food that is recommended (just true or false)

      6. Log to the console whether there is any dog eating an OKAY amount of food (just true or false)

      7. Create an array containing the dogs that are eating an OKAY amount of food (try to reuse the condition used in 6.)

      8. Create a shallow copy of the dogs array and sort it by recommended food portion in an ascending order (keep in mind that the portions are inside the array's objects)

    HINT 1: Use many different tools to solve these challenges, you can use the summary lecture to choose between them 😉

    HINT 2: Being within a range 10% above and below the recommended portion means: current > (recommended * 0.90) && current < (recommended * 1.10). Basically, the current portion should be between 90% and 110% of the recommended portion.

    TEST DATA:
    const dogs = [
      { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] },
      { weight: 8, curFood: 200, owners: ['Matilda'] },
      { weight: 13, curFood: 275, owners: ['Sarah', 'John'] },
      { weight: 32, curFood: 340, owners: ['Michael'] }
    ];

*/

const dogs = [
  { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] },
  { weight: 8, curFood: 200, owners: ['Matilda'] },
  { weight: 13, curFood: 275, owners: ['Sarah', 'John'] },
  { weight: 32, curFood: 340, owners: ['Michael'] }
];

// 1.
dogs.map(dog => dog.recFood = Math.trunc(dog.weight ** 0.75 * 28)); console.log(dogs)

// 2.
const dogSarah = dogs.find(dog => dog.owners.includes('Sarah'));
console.log(`Sarah's dog eating too ${dogSarah.curFood > dogSarah.recFood ? 'much.' : 'little.'}`);

// 3.
const ownersEatTooMuch = dogs.filter(dog => dog.curFood > dog.recFood).flatMap(dog => dog.owners);
const ownersEatTooLittle = dogs.filter(dog => dog.curFood < dog.recFood).flatMap(dog => dog.owners);
console.log(ownersEatTooLittle)

// 4.
console.log(`${ownersEatTooMuch.join(' and ')}'s dogs eat too much!`);
console.log(`${ownersEatTooLittle.join(' and ')}'s dogs eat too little!`);

// 5.
console.log(dogs.some(dog => dog.curFood === dog.recFood));

// 6.
const checkEatingOkay = dog => dog.curFood > dog.recFood * .9 && dog.curFood < dog.recFood * 1.1;
console.log(dogs.some(checkEatingOkay));

// 7.
const dogsEatOK = dogs.filter(checkEatingOkay);

// 8.
const dogsSorted = dogs.slice().sort((a, b) => a.recFood - b.recFood);
console.log(dogsSorted);
JavaScript