Home > Enterprise >  convert while loop to .forEach has unexpected result
convert while loop to .forEach has unexpected result

Time:09-21

In a helpful example of how to sort an array of objects using multiple properties the code that performs the sort uses a while loop (see students1 in code snippet below). I'm trying to simplify the while loop by using .forEach but get a different result set (see students2). Where did things go wrong in the refactoring using .forEach that it doesn't give the same output as the while loop?

const students = [
    {
        firstName: 'John',
        lastName: 'Appletree',
        grade: 12
    },
    {
        firstName: 'Mighty',
        lastName: 'Peachtree',
        grade: 10
    },
    {
        firstName: 'Kim',
        lastName: 'Appletree',
        grade: 11
    },
    {
        firstName: 'Shooter',
        lastName: 'Appletree',
        grade: 12
    },
    {
        firstName: 'Peter',
        lastName: 'Peachtree',
        grade: 12
    }
];

const sortBy = [
    {
      prop:'grade',
      direction: -1
    },
    {
      prop:'lastName',
      direction: 1
    }
];

const students1 = JSON.parse(JSON.stringify(students));
const students2 = JSON.parse(JSON.stringify(students));

students1.sort((a, b) => {
  let i = 0, result = 0;
  while (i < sortBy.length && result === 0) {
    const prop = sortBy[i].prop;
    const direction = sortBy[i].direction;
    result = direction *
        (
             a[prop].toString() < b[prop].toString() ? -1 :
            (a[prop].toString() > b[prop].toString() ? 1 : 0)
        );
    i  ;
  }
  return result;
});

students2.sort((a, b) => {
  let result = 0;
  sortBy.forEach(o => {
    result = o.direction *
    (
         a[o.prop].toString() < b[o.prop].toString() ? -1 :
        (a[o.prop].toString() > b[o.prop].toString() ? 1 : 0)
    );
  });
  return result;
});

console.log(students);
console.log('one', students1);
console.log('two', students2);

CodePudding user response:

Your forEach and while loops are not really equivalent. If the while condition was just i < sortBy.length, then it would work. Bit here you have an additional condition of result === 0, which forEach doesn't account for.

CodePudding user response:

You have not fully implemented the condition from the while loop:

const students = [
    {
        firstName: 'John',
        lastName: 'Appletree',
        grade: 12
    },
    {
        firstName: 'Mighty',
        lastName: 'Peachtree',
        grade: 10
    },
    {
        firstName: 'Kim',
        lastName: 'Appletree',
        grade: 11
    },
    {
        firstName: 'Shooter',
        lastName: 'Appletree',
        grade: 12
    },
    {
        firstName: 'Peter',
        lastName: 'Peachtree',
        grade: 12
    }
];

const sortBy = [
    {
      prop:'grade',
      direction: -1
    },
    {
      prop:'lastName',
      direction: 1
    }
];

const students1 = JSON.parse(JSON.stringify(students));
const students2 = JSON.parse(JSON.stringify(students));

students1.sort((a, b) => {
  let i = 0, result = 0;
  while (i < sortBy.length && result === 0) {
    const prop = sortBy[i].prop;
    const direction = sortBy[i].direction;
    result = direction *
        (
             a[prop].toString() < b[prop].toString() ? -1 :
            (a[prop].toString() > b[prop].toString() ? 1 : 0)
        );
    i  ;
  }
  return result;
});

students2.sort((a, b) => {
  let result = 0;
  sortBy.forEach(o => {
    if (result !== 0) return;
    result = o.direction *
    (
         a[o.prop].toString() < b[o.prop].toString() ? -1 :
        (a[o.prop].toString() > b[o.prop].toString() ? 1 : 0)
    );
  });
  return result;
});

console.log(students);
console.log('one', students1);
console.log('two', students2);

  • Related