Sort the array based on two criteria

Here is an array of objects with mock timestamps:

var firstArr = [{
  id: 1,
  a: 2,
  timestemp: 111
}, {
  id: 2,
  a: 4,
  timestemp: 222
}, {
  id: 3,
  a: 6,
  timestemp: 333
}, {
  id: 1,
  a: 3,
  timestemp: 777
}, {
  id: 3,
  a: 5555,
  timestemp: 5555
}];

I want to filter this array and create a new array with unique values.

The final array I'm looking for is:

var endArr = [{
  id: 1,
  a: 3,
  timestemp: 777
}, {
  id: 2,
  a: 4,
  timestemp: 222
},  {
  id: 3,
  a: 5555,
  timestemp: 555
}];

To achieve this, I need to filter the array by two criteria:

  1. Unique ID (only entries with IDs 1 & 3 appear once)
  2. Timestamp (include only objects with the latest timestamp)

Is it possible to accomplish this using array methods like map/reduce/filter?

I attempted to use array.filter but was unsuccessful.

Answer №1

If you want to retrieve items with unique IDs and the latest timestamps, you can use the functions orderBy() and uniqBy():

var sampleArray = [{
  id: 1,
  value: 2,
  timestamp: 111
}, {
  id: 2,
  value: 4,
  timestamp: 222
}, {
  id: 3,
  value: 6,
  timestamp: 333
}, {
  id: 1,
  value: 3,
  timestamp: 777
}, {
  id: 3,
  value: 5555,
  timestamp: 5555
}];

var resultArray = _(sampleArray)
.orderBy(['id', 'timestamp'], ['asc', 'desc'])
.uniqBy('id')
.value();

console.log(resultArray);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

Answer №2

At first glance, you misspelled timestamp as timestemp.

var firstArr = [{
  id: 1,
  a: 2,
  timestamp: 111
}, {
  id: 2,
  a: 4,
  timestamp: 222
}, {
  id: 3,
  a: 6,
  timestamp: 333
}, {
  id: 1,
  a: 3,
  timestamp: 777
}, {
  id: 3,
  a: 5555,
  timestamp: 5555
}];

Behold the function below:

function updateList(a_list) {

    var seen = {};

    for (var entry in a_list) {
        var id = a_list[entry]["id"];

        if (seen.hasOwnProperty(id)) {
            var current_timestamp = seen[id]["timestamp"]
            var check_timestamp = a_list[entry]["timestamp"]

            if (current_timestamp < check_timestamp) {
                 seen[id] = a_list[entry];
            }

        } else {
            seen[id] = a_list[entry];
        }
    }

    var updated = [];
    for (var newest in seen) {
        updated.push(seen[newest]);
    } 
    return updated;
} 

https://jsfiddle.net/vpg3onqm/
If this solution meets your needs, be sure to upvote and select it as the accepted answer.

Answer №3

When faced with the requirement to utilize filter, map, or reduce, I believe the following approach would be suitable:

var latestById = firstArr.reduce(function(state, curr) {
  if(state[curr.id]){ // Check if id has been encountered before
     if(curr.timestamp > state[curr.id].timestamp) { // If current item is more recent
        state[curr.id] = curr; // Update as latest item
     }
  } else {
     state[curr.id]  = curr; // Add because it's a new id
  }

  return state; // Pass updated state to next array element
}, {});

var endArr = Object.keys(latestById)
    .map(function (key) {return bestPerId[key]});

This code initializes an empty state object ({}), iterates through each item in firstArr, and determines if the id is known. If so, it tracks the item with the highest timestamp in the state. The updated state is passed on for each element in firstArr. Since the result is an object (with id's as keys and corresponding items as values), we convert it back to an array using map.

Answer №4

To ensure this method works effectively, it is crucial that the array firstArr is arranged in ascending order based on timestamps. The resultant array will also maintain timestamp-based ordering.

The algorithm begins by scanning the array from the end (largest timestamps) and adds each element to the new array only if it has not been included before. The array found acts as a tracker for extracted elements.

var found = [];
firstArr.reverse().filter( function(el){

  if( found.indexOf( el.id ) === -1 ){
    found.push( el.id );
    return true;
  }
  return false;

}).reverse();

Answer №6

To begin, you can arrange the elements by timestamp and then eliminate duplicate ids:

var firstArr = [
    { id: 1, a: 2, timestemp: 111 },
    { id: 2, a: 4, timestemp: 222 },
    { id: 3, a: 6, timestemp: 333 },
    { id: 1, a: 3, timestemp: 777 },
    { id: 3, a: 5555, timestemp: 5555 }
];

// sorting firstArr by descending timestamp:
firstArr.sort((x,y)=>y.timestemp-x.timestemp);

// retaining only the initial instance of each id:
var endArr = firstArr.filter((o,i)=>i==firstArr.findIndex(u=>u.id==o.id));

// task completed
output.innerHTML = JSON.stringify( endArr, null, 2 );
<pre id=output>

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 the value of a number in Angular be changed without altering its original value?

Imagine having the initial number 100. If I enter 50 in another input, it should add 50 to 100. However, if I then change the value from 50 to 80, the total should be 180 and not 230. The goal is always to add numbers to the original sum, not the new valu ...

Using AngularJS to send the $http response back to the calling object

Is there a way to pass the response value to the parent object, specifically the invoker of an http service call in AngularJS? I have a BaseModel that performs the GET request as shown below. The goal is for the basemodel object instance to hold the respon ...

Switch the designation to Hover Class

I am working with nested divs and have assigned a CSS class to one of the inner divs. How can I trigger the hover effect of the class (class.hover) when the user hovers over the outer div, even if they are not directly over the inner div? I believe this m ...

Why does $http.get succeed but I can't retrieve the output?

How can I retrieve the output from my remote server? - After verifying with Firebug, it seems that the JSON output is correct. Below is my approach, aiming for standardization (Plnkr): app.js, controllers.js, factories.js 'use strict'; var name ...

Turn off spellcheck for all material-ui elements

Is there a way to deactivate spellcheck globally for elements in the material-ui library? Before incorporating the material-ui library into my project, I used the code below to turn off spellcheck for all new DOM elements: const disableSpellCheck = funct ...

Is it possible to replicate the functionality of "npm run x" without including a "scripts" entry?

If you want to run a node command within the "context" of your installed node_modules, one way to do it is by adding an entry in the scripts field of your package.json. For example: ... "scripts": { "test": "mocha --recursive test/**/*.js --compiler ...

Unable to retrieve HTML content through a Node.js server

I created a HTML webpage that includes .css, images and JavaScript files. However, when I start my node server using the command below: app.get('/', function(req, res){ res.sendFile(__dirname + '/index.html'); }); The webp ...

Using values from a preexisting array to generate new arrays in JavaScript

I'm currently facing a challenge in JavaScript where I need to generate arrays based on the values of another array. For instance, I have an array of dates in string format (dates) listed below: ["30/09/2015", "31/10/2015", "30/11/2015", "31/12/2015 ...

Error encountered in React while using an object in useState: TypeError - Unable to access property 'name' of undefined

Encountering an issue with receiving JSON data from a route. When logging the data, it shows up correctly. However, when passing it to setProfileData(data), the updated state becomes undefined. Interestingly, when using setProfileData(data.user.name), it ...

How can one smoothly rewind X frames in a video or animation on a webpage without experiencing lag?

For my thesis presentation, I decided to make it available online as a video with custom controls resembling a powerpoint slideshow. The challenge I encountered was with transitions between slides in an animated video. Certain transitions needed to loop fo ...

Incorporating the non-typescript npm package "pondjs" into Meteor applications using typescript files

Implementing the Pondjs library into my project seemed straightforward at first: meteor npm install --save pondjs However, I'm encountering difficulties when trying to integrate it with my Typescript files. The documentation suggests: In order ...

Is it possible to incorporate multiple IDs into the changeImage function for a radio

I've encountered an issue with my function that changes images based on radio button selections. It works fine for one image slider, but now I want to make it available for a second slider. The problem is that when I use the radio buttons for the seco ...

What is the best method for adding files to JSZip from a remote URL?

Is it possible to load files into a Zip folder from a specified URL? For example: var zip = new JSZip(); zip.file("file.txt", "/site.net/files/file.txt"); Update I am following this example: I attempted the code provided but it was unsuccessful. I do ...

Tips for updating the chosen value with jquery or javascript

I am facing a situation where I need to change the selected option in a dropdown menu using a function triggered onClick later in the application. <select id="myselect"> <option value=aa>aa</option> <option value=bb>bb</option&g ...

What is the significance of declaring a constant array in JavaScript?

Does declaring an array as a constant in JavaScript prevent it from changing size, or does it mean that the values inside the array cannot be modified? handleClick(i) { const squares = this.state.squares.slice(); squares[i] = 'X'; this.setState( ...

The JavaScript object is unable to reach the PHP controller

When I attempt to send a JavaScript Object to my PHP controller, it is arriving empty. Here is the object: https://i.sstatic.net/19gFV.png Upon arrival, the object appears empty. Here is my AJAX code: https://i.sstatic.net/ekHsC.png var SendMovs = { ...

How to Use Jquery to Delete a Specific String

I've been attempting to remove certain strings from a string using Jquery, however it seems like the code isn't working and my variable remains unchanged. var classes = $("body").attr('class'); alert('.side-nav' + classes); c ...

In the world of programming, what sets a pointer to pointer apart from a pointer to array?

When I type the following code: char array[] = "some text"; char **ptr = &array; printf("%s\n",*ptr); No output is printed and a warning message appears: warning: initialization from incompatible pointer type [enabled by default] However, if I ...

Implementing live reload in a React application using docker-compose

Currently, I am managing two services: the front-end (product-list) and the back-end (server-api). To streamline their deployment, I have set up a docker-compose file which is running smoothly: version: '3.1' services: server-api: build: ...

The backtick is not functioning correctly when trying to append the result in the Internet Explorer browser

I am using the .html method to append HTML content to a specific div ID within my file. <html> <head> Title <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> </head> <body> ...