Arrange array of objects with unspecified and non-existent values

Is there a way to sort an array of objects in JavaScript that contains null and undefined values? The goal is to display items with a "jobTitle" property first, sorted by rating, followed by items without a "jobTitle" also sorted by rating. Sample Data:

data = [
  {name: 'John', rating: null},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'}
]

Once the data is sorted by jobTitle and then by rating, it should look like this:

[
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'},
  {name: 'Abba', rating: 5.44},
  {name: 'John', rating: null}
]

I have attempted various methods such as:

data.sort(function (a, b) {
  var x = a[key]; var y = b[key];
  return ((x > y) ? -1 : ((x < y) ? 1 : 0));
});

However, these approaches did not handle undefined and null values properly. I'm looking for a solution that does not involve creating new arrays or merging data, ideally completing the task within a single method.

EDIT

The desired outcome is to first list items with jobTitles sorted by their ratings AND then list those without jobTitles, also sorted by rating.

Answer №1

To ensure the desired outcome, it is important to evaluate each condition individually and provide the appropriate response for each scenario.

data = [
  {name: 'John', rating: null},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'}
];

data.sort((a, b) => {
  if(a.jobTitle && b.jobTitle) {
    return (b.rating || 0) - (a.rating || 0);
  } else if(a.jobTitle || b.jobTitle) {
    return !(a.jobTitle) - !(b.jobTitle)
  } else  {
    return (b.rating || 0) - (a.rating || 0);
  }
});
console.log(data)

Answer №2

If you're looking to optimize your code, I suggest breaking it down into two separate sorts and executing them in a sequence.

let categories = [
  {name: 'John', rating: null},
  {name: 'Peter', rating: null},
  {name: 'Harry', rating: 0.44, jobTitle: 'plumber'},
  {name: 'Harry', rating: 0.50, jobTitle: 'plumber'},
  {name: 'Anderson', rating: 1.34, jobTitle: 'mascot'},
  {name: 'Ethel', rating: 1.34, jobTitle: 'engineer'},
  {name: 'Abba', rating: 5.44}
]
categories.sort(sortByRating);
categories.sort(sortByJobTitle);
console.log(categories)

function sortByJobTitle(a, b){
  if( typeof a.jobTitle === 'undefined' && typeof a.jobTitle === 'undefined' ) return 0;
  if( typeof b.jobTitle === 'undefined' ) return -1;
  if( typeof a.jobTitle === 'undefined' ) return 1;
  
  let titleA = a.jobTitle.toLowerCase();
  let titleB = b.jobTitle.toLowerCase();
  
  if( titleA === titleB ) return 0;
  if( titleA > titleB ) return 1;
  else return -1;
}

function sortByRating(a, b) {
  // This comparison works for null because it gets cast to 0
  if( a.rating === b.rating ) return 0;
  if( a.rating > b.rating ) return -1;
  else return 1;
}

Answer №3

When implementing your sort function, it's important to consider how to handle cases where a value is either null or undefined. In such scenarios, you can opt to return 1, ensuring that the element is sorted to the end of the array. Furthermore, it's worth noting that you are sorting an array in this context, not a JSON string. Remember that a JSON string cannot include the undefined primitive value, although this is permissible in valid JavaScript syntax.

data.sort(function (a, b) {
  var x = a[key];
  var y = b[key];
  if (x === null || x === undefined) {
    return 1;
  }
  return y - x;
});

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

Issue with Vue JS Components: Button function not working on second click with @click

I've been working with Vue JS and Laravel to create a modal. The first time I press the button with @click, it works fine but the next time I encounter an error. Here's my Laravel Blade code: <div class="col-span-12 mb-5" id="a ...

Troubles with retrieving Array data for a JavaScript column chart

I am currently developing a Flask app in Python and utilizing render_template to send back 2 arrays, "names" and "deals", to my HTML file. I have confirmed that these arrays are working correctly based on the code snippet below that I tested, which display ...

Incorporating Keyboard Features into Buttons

How can I toggle the page selectors in #pageList using a keyboard shortcut instead of clicking on the .togglePL button? I've tried looking up solutions online and asking questions here, but haven't found a working solution yet. Below is the code ...

Utilizing Threejs to implement dynamic text labels

Recently, after reading a discussion on stackoverflow, I decided to incorporate labels into my canvas. To achieve this, I created a second scene and camera to overlay the labels on top of the first scene. this.sceneOrtho = new THREE.Scene();//for labels t ...

Issues with jQuery spinner not currently active

For quite some time, I had this code working perfectly in my Rails application: $(function () { // Modifying the link's icon while the request is in progress $(document).on('click', 'a[data-remote]', function () { ...

Having trouble drawing over buttons in HTML5 Canvas?

window.addEventListener("load", () => { const canvas = document.querySelector("#canvas"); const ctx = canvas.getContext("2d"); const color = document.querySelector("#color"); const strokeWeight = document.querySelector("#strokeWeight"); ...

Utilizing AJAX in jQuery Mobile for Collapsible Content

I am currently generating a variable number of these elements using a foreach() loop: <div id="<?php echo $data['id']; ?>" data-role="collapsible" data-theme="a"> <h1 style="white-space: normal"><?php echo $data['te ...

Transferring data from a text area to a table with AngularJS

Creating a C# MVC App with AngularJS My goal is to populate a table with values entered in a text area using Angular. Here is the process: Users input values into a text area like this: A B C When a user clicks a button, a modal window should open and ...

Show a compact graphic in the upper-right-hand corner

Hey, I have this interesting idea but CSS isn't my strong suit. Any thoughts on how to achieve it? I'm looking to create a new class that, when applied to an item (like a div), displays a small clickable pre-defined image in the Top-Right corne ...

Efficiently Filtering User Input and Other Things

Imagine I have a setup for organizing a television guide like this: <div class="day"> <p>A Date</p> <div class="time"> <p>A Time</p> <div class="show"> <p>A Show</p> ...

Display words on screen and then alter hue using HTML and CSS

Is there a way to dynamically change the color of text inside <a> tags from black to red after a specific time interval and keep it permanently red? do { document.getElementById("code").innerHTML +="<a>Hello World</a><br>"; awa ...

Position the caret after adding a new element in a content-editable div

I have a contenteditable div that contains various elements. My goal is to automatically create a new paragraph tag right after the element where the cursor is positioned when the user presses the enter key. Currently, I am able to insert the paragraph tag ...

Guide on populating a textbox with values through Ajax or Jquery

Consider the scenario where there are three textboxes. The first textbox requires an ID or number (which serves as the primary key in a table). Upon entering the ID, the semester and branch fields should be automatically filled using that ID. All three fie ...

I'm experiencing a flickering issue with my carousel when it reaches over 10,000 pixels during animation. Could this be related to a jQuery problem

After my carousel moves past 10000 pixels, it starts flickering through multiple elements. I'm utilizing jCarousel Lite: Could this be a jQuery-related issue? My initial assumption is that it may be specific to jCarousel Lite, but there doesn't ...

Looking for a specialized search function that handles special characters and numbers

I have created a loop to iterate through characters in the alphabet. However, the issue I'm facing now is that the "#" symbol does not select all the titles with special characters or numbers. <?PHP $page_nav = array(); $r = 35; $rr = chr($r); fo ...

Encountered an error while attempting to load resource in Node.js

I'm currently working on a project utilizing Node js (Express...). Let me do my best to explain the issue I am encountering. My work is being done on localhost, and the main page of my index.html has buttons that lead to other pages when clicked. I c ...

Is it possible to iterate through HTML elements without relying on forEach()?

Currently working on my web-based system using Node.js and HTML. Are there any alternative ways to iterate through HTML elements without using forEach? I'm considering something like this (for example): <% for(var ctr=0; ctr<arrayname.length ...

Utilize fixed values in type declaration

Strange Behavior of Typescript: export type MyType = 0 | 1 | 2; The above code snippet functions correctly. However, the following code snippet encounters an issue: export const ONE = 1; export const TWO = 2; export const THREE = 3; export type MyType = O ...

Sending Array Data from Controller to Factory in AngularJS

Can array data be transmitted from a controller to a factory, extracted from the factory, and then inserted into a database using Slim framework? Array[{}] CONTROLLER -> FACTORY -> SLIM PHP FRAMEWORK -> DATABASE I am new to AngularJS. Could you ...

A guide to sorting an object with integer keys by its values using JavaScript

I am facing an issue with sorting a map by values instead of keys. No matter what I do, it always ends up getting sorted by the keys. On the server side, I have a map that is already sorted. When I send this map to JavaScript using JSON, it gets re-ordere ...