Home > OS >  Javascript Object.keys(arr).reduce() return lowest key
Javascript Object.keys(arr).reduce() return lowest key

Time:01-18

I have 3 different test cases, each of which is passed to the function getEarliest below:

{}

{ '2022-04-29': 1 }

{ '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 }

From each test case, I want to return the key:value with the smallest date and the biggest value. My problem is at the third test case, I'm getting '2022-04-29': 3 instead of '2022-04-28': 3

getEarliest = dates => {

    return Object.keys(dates).reduce((prev, curr) => {

        if (dates[curr] > prev.date) {
        
            return {
                val: dates[curr],
                date: curr
            };
        } else {
            return prev;
        }
    }, {
        val: 0,
        date: null
    }); }

expected result test case 1 : { val: 0, date: null }

expected result test case 2 : { val: 1, date: '2022-04-29' }

expected result test case 3 : { val: 3, date: '2022-04-28' }

CodePudding user response:

In your code prev.date value is initially null. so reduce() will always return the initial object.

Try this code it's help you

 getEarliest = (dates) => {
      if (Object.keys(dates).length > 0) {
        let date = Object.keys(dates).reduce((prev, curr) => {
          if (prev > curr) {
            return curr;
          } else {
            return prev;
          }
        });

        return {
          val: dates[date],
          date: date
        }
      } else {
        return {
          val: 0, date: null
        }
      }
    }

CodePudding user response:

Because you have 2 sort conditions so they have to be put in a certain order. From your examples I assume that order is: "biggest value" -> "smallest date". Then your if will become like below:

getEarliest = (dates) => {
  return Object.keys(dates).reduce(
    (prev, curr) => {
      if (dates[curr] > prev.val || (dates[curr] === prev.val && curr < prev.date)) {
        return {
          val: dates[curr],
          date: curr,
        }
      } else {
        return prev
      }
    },
    {
      val: 0,
      date: null,
    }
  )
}

CodePudding user response:

Looks like you need just sort object by two parametrs:

const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };

  
const getEarliest = (dates) => {
  const [date, val] = Object.entries(dates)
    .sort(([k1, v1], [k2, v2]) => v2 - v1 || Date.parse(k1) - Date.parse(k2) ) 
    .at(0) ?? [null, 0];

  return { val, date };
};

console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100% !important; top: 0}

And the same result with reduce:

const test1 = {};
const test2 = { '2022-04-29': 1 };
const test3 = { '2022-04-29': 3, '2022-04-30': 2, '2022-04-28': 3, '2022-05-02': 2 };
const test4 = { '2022-04-29': 4, '2022-04-28': 4, '2022-04-30': 4, '2022-05-02': 2 };

  
const getEarliest = (dates) => {
  const [date, val] = Object.entries(dates)
    .reduce((prev, curr) => (curr[1] - prev[1] || Date.parse(prev[0]) - Date.parse(curr[0])) > 0  
      ? curr 
      : prev
    , [null, 0]);
  
  return { val, date };
};

console.log(getEarliest(test1));
console.log(getEarliest(test2));
console.log(getEarliest(test3));
console.log(getEarliest(test4));
.as-console-wrapper {max-height: 100%!important;top:0 }

  •  Tags:  
  • Related