Retrieve the latest item for each unique name in Javascript

Here are some snippets of data extracted from the crt.sh website regarding current SSL certificates.

[
    {
        "name_value": "unifi.borpin.net",
        "id": 4306577133,
        "not_after": "2021-06-29T20:02:05",
    },
    {
        "name_value": "unifi.borpin.net",
        "id": 4306565152,
        "not_after": "2021-06-29T20:00:00",
    },
    {
        "name_value": "hassio.borpin.net",
        "id": 4264152857,
        "not_after": "2021-06-22T02:01:45",
    },
    {
        "name_value": "unifi.borpin.net",
        "id": 4305553329,
        "not_after": "2021-06-29T16:15:11",
    },
    {
        "name_value": "hassio.borpin.net",
        "id": 3966036743,
        "not_after": "2021-04-22T12:18:00",
    }
]

I am looking for a way to create an array that includes only the entry with the latest expiration date (not_after). This is usually the first entry in the list but not always guaranteed.

The desired output should be:

[
    {
        "name_value": "unifi.borpin.net",
        "id": 4306577133,
        "not_after": "2021-06-29T20:02:05",
    },
    {
        "name_value": "hassio.borpin.net",
        "id": 4264152857,
        "not_after": "2021-06-22T02:01:45",
    }
]

Answer №1

I am looking to create an array with one entry for each domain, where the entry represents the domain with the latest expiration date (*not_after*).

To achieve this efficiently, you can utilize the Array#reduce method which has a time complexity of O(n).

The approach involves consolidating all items and implementing the following logic:

  1. If the item does not exist, create a new entry for it.
  2. If the item exists and the current *not_after* value is greater than the existing one, update the *not_after* value.

const items = [{"name_value": "unifi.borpin.net", "id": 4306577133, "not_after": "2021-06-29T20:02:05" },{"name_value": "unifi.borpin.net", "id": 4306565152, "not_after": "2021-06-29T20:00:00", }, { "name_value": "hassio.borpin.net","id": 4264152857,"not_after": "2021-06-22T02:01:45", },{"name_value": "unifi.borpin.net","id": 4305553329,"not_after": "2021-06-29T16:15:11",},{ "name_value": "hassio.borpin.net", "id": 3966036743, "not_after": "2021-04-22T12:18:00", }];

const result = items.reduce((acc, curr) => {
  const existingItem = acc[curr.name_value];
  if(!existingItem)
    acc[curr.name_value] = curr;
  else if(new Date(existingItem.not_after) < new Date(curr.not_after))
    existingItem.not_after = curr.not_after;
  
  return acc;
}, {});

console.log(Object.values(result));

Answer №2

One way to achieve this is by utilizing a custom sorting function along with Array.prototype.reduce.

To simplify the process, we can start by sorting the array based on dates in ascending order. This allows us to easily assign values to object properties without the need for conditional checks. The last element will be considered as the recent element.

const arr = [{
    name_value: "unifi.borpin.net",
    id: 4306577133,
    not_after: "2021-06-29T20:02:05",
  },
  {
    name_value: "unifi.borpin.net",
    id: 4306565152,
    not_after: "2021-06-29T20:00:00",
  },
  {
    name_value: "hassio.borpin.net",
    id: 4264152857,
    not_after: "2021-06-22T02:01:45",
  },
  {
    name_value: "unifi.borpin.net",
    id: 4305553329,
    not_after: "2021-06-29T16:15:11",
  },
  {
    name_value: "hassio.borpin.net",
    id: 3966036743,
    not_after: "2021-04-22T12:18:00",
  },
];

const obj = arr
  .sort((a, b) => {
    return new Date(a.not_after) - new Date(b.not_after);
  })
  .reduce((acc, curr) => {
    acc[curr.name_value] = curr;
    return acc;
  }, {});

const result = Object.values(obj);
console.log(result);

Answer №3

Give this method a try. The detailed explanation can be found within the comments.

let data = [{
    "name_value": "unifi.borpin.net",
    "id": 4306577133,
    "not_after": "2021-06-29T20:02:05",
  },
  {
    "name_value": "unifi.borpin.net",
    "id": 4306565152,
    "not_after": "2021-06-29T20:00:00",
  },
  {
    "name_value": "hassio.borpin.net",
    "id": 4264152857,
    "not_after": "2021-06-22T02:01:45",
  },
  {
    "name_value": "unifi.borpin.net",
    "id": 4305553329,
    "not_after": "2021-06-29T16:15:11",
  },
  {
    "name_value": "hassio.borpin.net",
    "id": 3966036743,
    "not_after": "2021-04-22T12:18:00",
  }
];

let result = data.reduce((a, i) => {
  // locate existing object for name_value 
  let obj = a.filter(x => x.name_value === i.name_value)[0];

  // if obj doesn't exist, create a new object and copy all values from item to it
  if (!obj) {
    obj = { ...i };
    // add the object to the result array
    a.push(obj);
  } else if (new Date(obj.not_after) < new Date(i.not_after)) {
    obj.id = i.id;
    obj.not_after = i.not_after;
  }

  return a;
}, []);

console.log(result);

Answer №4

There are various methods to achieve this task.

For instance, we can start by identifying the most recent date for each domain using an object. Subsequently, we can convert the finalized object into an array.

Please note: To ensure accurate date comparisons, we must convert your string values into dates.

In this scenario, the corresponding code would resemble the following:

const inputArray = [{
  "name_value": "unifi.borpin.net",
  "id": 4306577133,
  "not_after": "2021-06-29T20:02:05",
},
  {
    "name_value": "unifi.borpin.net",
    "id": 4306565152,
    "not_after": "2021-06-29T20:00:00",
  },
  {
    "name_value": "hassio.borpin.net",
    "id": 4264152857,
    "not_after": "2021-06-22T02:01:45",
  },
  {
    "name_value": "unifi.borpin.net",
    "id": 4305553329,
    "not_after": "2021-06-29T16:15:11",
  },
  {
    "name_value": "hassio.borpin.net",
    "id": 3966036743,
    "not_after": "2021-04-22T12:18:00",
  }
];

const lastExpires = inputArray.reduce((result, item) => {
  if (
    !result[item.name_value] ||
    new Date(result[item.name_value].not_after) < new Date(item.not_after)
  ) {
    result[item.name_value] = item;
  }

  return result;
}, {});

const outputArray = Object.values(lastExpires);

console.log(JSON.stringify(outputArray, null, 4));

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

I am attempting to add a button at the conclusion of every row within my table using JavaScript

My challenge is to add buttons to the end of each row in a dynamic table using JavaScript for appending. However, every time I attempt this, it only adds a button at the end of the last row. Here's an image depicting the issue: View Image <!--TABLE ...

What is the process for incorporating controls within the three.js editor interface?

First and foremost, I want to express my gratitude for your assistance and understanding! As someone relatively new to coding, I have been exploring the various examples provided by three.js. By following these examples, I have successfully created a basic ...

The AngularJS framework is failing to disable the autocomplete feature for the input field with a password type

I have attempted to disable auto-complete for the password input, but it doesn't seem to be working. Below is a sample of my code: <form name="testfrm" ng-submit="test(testfrm)" autocomplete="off"> <input type="password" id="passwor ...

Having trouble selecting a default option in a dynamically populated select dropdown using ng-model in the dropdown

For my Angularjs application, I needed to dynamically return a select drop down with its selected option. To accomplish this, I implemented the following function: function getCellRendererMapping(data) { if (data.order == 6) { return funct ...

Challenges with declarations and operators

Hi everyone, I'm trying to tweak the order of operators in a code snippet so that the result logged is 0. Can someone help me figure this out? numbers = [23, 12, 71, 10] operators = [ (a, b) => a + b, (a, b) => a / b, (a, b) => a * b, (a, b) ...

Determining when a webpage first loads vs. being refreshed in JavaScript

I require the execution of a JavaScript function to occur after a web page has been refreshed, regardless of the method used (such as pressing F5, clicking the browser's refresh button, or re-entering the same URL). This action should only take place ...

The office web add-in is missing the necessary 'Access-Control-Allow-Origin' header on the requested resource

Currently, I am attempting to make a POST request to a REST API within the Office Outlook web add-in using AJAX calls. Despite configuring the app domains in the manifest.xml file for the target URL, I am encountering CORS issues. The error message reads: ...

Determining the optimal number of rows and columns based on an integer value

Here's a brain teaser for you: /** * Let's figure out the optimal number of rows and columns for your garden to be as square as possible, based on the number of seeds you have. * * @param {number} seedCount - The total number of seeds in you ...

Upon transmitting the information to the server, an error message pops up saying 'Uncaught TypeError: Illegal invocation'

I'm encountering an issue with sending an ajax request in my php-script. The jquery script I'm using selects certain fields from a form and sends them as arguments to a jquery function. However, upon sending the data to the server, I receive the ...

At what point should you invoke db.close() while utilizing cursor.forEach()?

When working with .toArray(), it is common practice to include db.close() within the callback function. For example: db.collection('grades').find(query).toArray(function(err, docs) { if (err) throw err; console.dir(docs); db.close(); }); ...

Unable to administer AuthenticationController

I am attempting to inject a controller into my app.run function, but I keep encountering the following error: Uncaught Error: [$injector:unpr] http://errors.angularjs.org/1.2.10/$injector/unpr?p0=AuthenticationControllerProvider%20%3C-%20AuthenticationCon ...

Error in Next.js: Trying to destructure an undefined object in useContext

While attempting to change the state of my cursor in a Next.js app using useContext, I encountered the following error: TypeError: Cannot destructure 'Object(...)(...)' as it is undefined. The goal is to update the state to isActive: true when h ...

What is the best way to utilize props in ReactJS to establish a condition that enables me to modify the state of my application?

Within my project, I have the "App" component serving as the parent and the Hero component which features an image along with left and right arrow functionalities. In order to achieve the desired functionality, I aim to utilize the right arrow to incremen ...

Configuring IP Whitelisting for Firebase Cloud Functions with MongoDB Cluster

What is the process for including my Firebase Cloud Functions in the IP whitelist of my MongoDB cluster? Error Message: ...

Tips for verifying the inclusion of the + symbol in the country code in Angular 7

My form includes a text box where users can input a country code preceded by a + sign. If a user enters only numbers, we need to restrict that action and prompt them to enter the country code with a + sign, for example: +91, +230, ... I've been tryin ...

The horizontal scroll menu transition in CSS is choppy and lacks smoothness

My goal is to create a seamless transition for the menu. However, when clicking the arrows, the 2nd div appears at the bottom of the 1st div, causing a choppy effect. Below is the code I am currently using: To view my code, please visit: ...

req.next does not exist as a function [END]

I am currently working on developing a website and I have encountered an issue in the dashboard stage. The error message TypeError: req.next is not a function keeps appearing, particularly when trying to create a subpage for the dashboard. I am utilizing t ...

AngularJS blank drop-down selection

I am currently working on an AngularJS select element with ng-options using the code below: <select ng-model="vm.selectedship" ng-change="vm.updateShip()" data-ng-options="ship as ('ship' + ' is ready (' + ship.currentlocation + & ...

The React popup window refuses to close on mobile devices

I am currently facing an issue with a site (a react app) deployed on GitHub pages. The site features cards that, when clicked on, should open a modal/dialog box. Ideally, clicking on the modal should close it. However, I have encountered a problem specific ...

What is the importance of having Actions and Reducers in Redux?

I am trying to grasp the reasoning behind the design of Redux. For instance, let's consider a scenario where I have a store with a list of todos. If the store is represented as an object like this: {1: todo1, 2: todo2, 3: todo3, ...}* And we enca ...