Find the smallest key in the array using JavaScript's Object.keys(arr) and the reduce

In my experiment, I have 3 distinct scenarios which are fed into the function findMinDateAndMaxValue:

{}

{ '2022-04-29': 1 }

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

My objective is to extract the key:value pair with the earliest date and the highest value from each scenario. However, in the third case, I encounter an issue where I get '2022-04-29': 3 instead of '2022-04-28': 3

findMinDateAndMaxValue = 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 outcome for scenario 1 : { val: 0, date: null }

expected outcome for scenario 2 : { val: 1, date: '2022-04-29' }

expected outcome for scenario 3: { val: 3, date: '2022-04-28' }

Answer №1

It appears that you simply need to sort the object by two parameters:

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}

You can achieve the same result using 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 }

Answer №2

The prev.date value in your code is originally set to null, which means that the reduce() function will always return the initial object.

You can try using this updated code for better results:

 getEarliest = (dates) => {
      if (Object.keys(dates).length > 0) {
        let earliestDate = Object.keys(dates).reduce((prevDate, currDate) => {
          if (prevDate > currDate) {
            return currDate;
          } else {
            return prevDate;
          }
        });

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

Answer №3

With 2 sort conditions in play, the order becomes crucial for accurate results. Based on the examples provided, it seems that the preferred order is: "largest value" followed by "earliest date". In this case, your if statement should be structured as shown below:

findEarliest = (dates) => {
  return Object.keys(dates).reduce(
    (previous, current) => {
      if (dates[current] > previous.value || (dates[current] === previous.value && current < previous.date)) {
        return {
          value: dates[current],
          date: current,
        }
      } else {
        return previous
      }
    },
    {
      value: 0,
      date: null,
    }
  )
}

Answer №4

  • The initial statement lacks a definition for the .date property, resulting in it being undefined. Since dates is an array and not an object, referencing dates[curr] as dates['2022-04-28'] provides no meaningful value. In notation like array[5], an integer serves as the index within the brackets, representing the third parameter of .reduce().

    if (dates[curr] > prev.date) {...
    
  • The appearance of "2022-04-29" occurs because the array remains unchanged; to resolve this, sorting the dates using .sort() is suggested as a simpler alternative compared to the complexity of .reduce(), especially for beginners.

Additional insights are provided in the following example

let A = {};

let B = {
  '2022-04-29': 1
};

let C = {
  '2022-04-29': 3,
  '2022-04-30': 2,
  '2022-04-28': 3,
  '2022-05-02': 2
};

// Utility function
const log = data => console.log(JSON.stringify(data));

/*
Timestamp to YYYY-MM-DD format conversion and vice versa
*/
const dX = (number, string) => {
  let D;
  if (number) {
    let date = new Date(number);
    D = `${date.getFullYear()}-${("0" + (date.getMonth() + 1)).slice(-2)}-${("0" + date.getDate()).slice(-2)}`;
  } else if (string) {
    D = Date.parse(string);
  } else {
    return false;
  }
  return D;
};

// Processing tS = {...}
const getEarliest = tS => {
  // if tS is empty...
  if (Object.keys(tS).length === 0) { // Return predefined object
    return {
      val: 0,
      date: null
    };
  }

  let table = Object.entries(tS).map(([k, v]) => [k, v]).sort((a, b) => dX(null, a[0]) - dX(null, b[0]));
  let obj = {};
  obj.val = table[0][1];
  obj.date = table[0][0];
  return obj;
};

log(getEarliest(A));
log(getEarliest(B));
log(getEarliest(C));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I convert hexadecimal to a string using C?

Hello, I am currently using digi dynamic c and I am attempting to convert the following data into a string: char readingreg[4]; readingreg[0] = 4a; readingreg[1] = aa; readingreg[2] = aa; readingreg[3] = a0; At this moment, my printf statements require f ...

Picked (chosen-js): Steps to deselect options using a variety of selectors

I am currently using the Chosen library on Vue and Webpack for my project. I have a scenario where I need to cancel a selection when multiple options are selected, but I am struggling to achieve this. Can anyone guide me on how to cancel a selected optio ...

Invoking a subclass's method within a base class in Typescript

Currently, I am in the process of developing a small game project and I am facing a particular challenge that I need a solution for. Within my code, I have a base class called 'Entity' which contains essential methods for its subclasses (objects ...

Is there a way to programmatically display a Chakra-UI Toast?

I'm currently struggling to programmatically display a Chakra-UI Toast using the Chakra-UI React.js component library. The Chakra-UI Toast documentation only provides examples of showing the toast based on a button click, but I'm looking to show ...

Ensuring that the text in the Bootstrap navbar is responsive for all screen

Yesterday, I inquired about how to modify my navbar menu to switch from horizontal to vertically arranged depending on layout. However, I've noticed that the responsiveness is not consistent when adjusting the window size. Is there a way to ensure my ...

Differentiating between mouseenter and tap events: What's the key?

When a mouseenter event is present, touch-enabled devices will activate this event when the user taps on the element. Is there a way to differentiate between an actual physical mouse entering and a simulated tap (which resembles a mouse enter)? ...

What is the best approach for writing an asynchronous function while utilizing $rootScope.broadcast within a continuous loop?

At least 10 times a second, I have a function that is called. Each time, there are approximately 100 records with variations in LastSeenTime and ReadCount. In this simulation scenario, I understand the behavior; however, in real-time, the number of records ...

Is there a way to refine results based on geographic location?

Hello fellow coders! I need assistance finding a lightweight JavaScript code that can filter based on geographical location. This script needs to first determine if the GPS is enabled or not. If disabled, redirect to www.no.com. If enabled, it should chec ...

Switching from using $.AJAX to using $.POST is a

Could someone assist me in changing this code to use $.post instead? I've tried replacing some of the code but it's not working properly. Thank you for your help. $.post({ url: "http://192.168.254.107/webs/main/ajax/validateLogin.php", ...

Navigating JSON Data in Groovy Using a Loop: A Handy Guide

Just starting out with Groovy and attempting to mock a service in SoapUI. The task at hand involves loading a text file containing JSON data, and then matching that data to a specific node. Here is what I have attempted so far: def inputFile = new File( ...

The download button consistently targets and downloads the initial SVG in my collection. How can I configure it to target each individual SVG for download?

I'm currently working on a QR code app using React. The goal is for users to submit a form with a value, which will then generate an SVG QR code that can be downloaded. However, I'm running into an issue where the same SVG file is being downloade ...

Troubleshoot: Why is my Google Chrome not playing videos? Uncover the solution with a

I have created a webpage with an HTML video tag that loads dynamically from a JSON file. I am currently using Chrome 50 for this project. The response is successful, and when inspecting the page using Chrome's developer tools, I can see the video tag ...

Migrate the JavaScript variable created with 'passport' to an Express router

In my quest for authentication, I created the essential passportAuth.js file: module.exports = function(passport, FacebookStrategy, config, mongoose, fbgraph){ passport.serializeUser(function(user,done){ //to make user reference available across pages ...

Extracting a precise value from an array nested within another array

Within my nested associative arrays, I am trying to figure out how to splice a specific value. In a regular array, this is easily done with: arr.splice(arr.indexOf('specific'), 1); But when it comes to an array structure like this: arr['h ...

Is there a way to retrieve the array ID from one page and pass it to a different redirect page?

Welcome to my first post! I've been on a quest to find exactly what I need but without much luck. Here's the situation: I have this file that breaks down the content of a post and includes a "read more" option: <?php include('../root/ad ...

What is the best way to incorporate a countdown timer on an ASP.NET webpage?

Looking to display a countdown timer in the top right corner of my ASP page that starts from 00:00:30 and counts down to 00:00:00 before resetting back to 00:00:30. Does anyone have any suggestions on how to achieve this? ...

Updating a column in a SQL Table via an Ajax request

I am attempting to store the on or off value from a form into an SQL database by calling a JS function with an AJAX request that sends it to a PHP page for processing. I seem to be facing some issues with my code and could really use some assistance as the ...

Determining the minimum and maximum values of a grid using props in a React component

I have created a code for a customizable grid screen that is functioning perfectly. However, I am facing an issue where I want the minimum and maximum size of the grid to be 16 x 100. Currently, when a button is clicked, a prompt window appears asking for ...

The jQuery functions seem to be malfunctioning when trying to retrieve elements by their ids

I'm having trouble with the click function when using IDs, but it works fine with classes. $('#myTab li a').click(function(e) {} When I switch to using classes like this: $('.nav-tabs a.overview').click(function(e) {} it work ...

Ways to troubleshoot the error message 't.rangeslider is not a function' in which rangeslider is a personalized function

I'm experiencing an issue with a function assigned to a variable that is throwing an error. Here is the code snippet: $(".sliderRange").each(function() { var t = $(this); t.rangeslider({ polyfill: !1, onSlide: function(e, a) { var n = ...