Arrange objects in an array according to the order specified in another array

Here is my array of car makes:

const makes = [
{id: "4", name: "Audi"},
{id: "5", name: "Bmw"},
{id: "6", name: "Porsche"},
{id: "31", name: "Seat"},
{id: "32", name: "Skoda"},
{id: "36", name: "Toyota"},
{id: "38", name: "Volkswagen"}
]

Now, I want to organize this array based on another list:

const preferred_makes = ['Volkswagen', 'Audi'];

This is how I currently approach it:

const preferred_makes = ['Volkswagen', 'Audi'];

const makes = [
{id: "4", name: "Audi"},
{id: "5", name: "Bmw"},
{id: "6", name: "Porsche"},
{id: "31", name: "Seat"},
{id: "32", name: "Skoda"},
{id: "36", name: "Toyota"},
{id: "38", name: "Volkswagen"}
]

const mainMakes = []
const otherMakes = []

makes.map(make => _.includes(preferred_makes, make.name) ? mainMakes.push(make) : otherMakes.push(make))

console.log(mainMakes)
console.log(otherMakes)

However, I'm wondering if there's a more efficient method. Is there a way to rearrange the makes array so that the elements from preferred_makes come first?

You can view the fiddle here.

Answer №1

If you need to sort an array with a custom comparison function, the array.sort() method in JavaScript can help you achieve that.

const favorite_brands = ['Nike', 'Adidas'];

const brands = [
  {id: "1", name: "Adidas"},
  {id: "2", name: "Puma"},
  {id: "3", name: "Reebok"},
  {id: "4", name: "Nike"},
  {id: "5", name: "Under Armour"}
]

const sortedBrands = brands.slice().sort((x, y) => {
  // Convert true and false to 1 and 0
  const xFavorite = new Number(favorite_brands.includes(x.name))
  const yFavorite = new Number(favorite_brands.includes(y.name))
  
  // Return 1, 0, or -1
  return yFavorite - xFavorite
})

console.log(sortedBrands)

Answer №2

To organize a list based on preferred values, create an object with incremented indices for specified names and set a default value of Infinity for names not found. Then, sort the array by comparing the delta of the values.

var preferred_makes = ['Volkswagen', 'Audi'],
    preferred = preferred_makes.reduce((o, k, i) => (o[k] = i + 1, o), {});
    array = [{ id: "4", name: "Audi" }, { id: "5", name: "Bmw" }, { id: "6", name: "Porsche" }, { id: "31", name: "Seat" }, { id: "32", name: "Skoda" }, { id: "36", name: "Toyota" }, { id: "38", name: "Volkswagen" }];

array.sort((a, b) => (preferred[a.name] || Infinity) - (preferred[b.name] || Infinity));

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Answer №3

One way to create two arrays without sorting is by using the reduce method:

const preferred_makes = ['Volkswagen','Audi'];
const makes = [{id:"4",name:"Audi"},{id:"5",name:"Bmw"},{id:"6",name:"Porsche"},{id:"31",name:"Seat"},{id:"32",name:"Skoda"},{id:"36",name:"Toyota"},{id:"38",name:"Volkswagen"}];

const [mainMakes, otherMakes] = makes.reduce(([a, b], { id, name }) => ((preferred_makes.includes(name) ? a : b).push({ id, name }), [a, b]), [[], []]);

console.log(mainMakes);
console.log(otherMakes);
.as-console-wrapper { max-height: 100% !important; top: auto; }

For improved performance, you could use Set.prototype.has instead of includes:

const preferred_makes = new Set(['Volkswagen','Audi']);
const makes = [{id:"4",name:"Audi"},{id:"5",name:"Bmw"},{id:"6",name:"Porsche"},{id:"31",name:"Seat"},{id:"32",name:"Skoda"},{id:"36",name:"Toyota"},{id:"38",name:"Volkswagen"}];

const [mainMakes, otherMakes] = makes.reduce(([a, b], { id, name }) => ((preferred_makes.has(name) ? a : b).push({ id, name }), [a, b]), [[], []]);

console.log(mainMakes);
console.log(otherMakes);
.as-console-wrapper { max-height: 100% !important; top: auto; }

Answer №4

Utilizing lodash allows you to create a mapping of the original index based on the car's make (indexByMake) by using _.invert() to generate an object containing

{ [car make]: original array index }
, then converting the values back to numbers.

Employing _.orderBy() facilitates sorting the array, with the values from indexByMake arranged according to the name:

const preferred_makes = ['Volkswagen', 'Audi'];
const array = [{ id: "4", name: "Audi" }, { id: "5", name: "Bmw" }, { id: "6", name: "Porsche" }, { id: "31", name: "Seat" }, { id: "32", name: "Skoda" }, { id: "36", name: "Toyota" }, { id: "38", name: "Volkswagen" }];

const indexByMake = _.mapValues(_.invert(preferred_makes), Number);

const result = _.sortBy(array, ({ name }) => indexByMake[name]);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

Answer №5

If the index is present, you can sort by using the Array.indexOf, otherwise resort to utilizing String.localeCompare. In this scenario, lodash isn't necessary:

const brands = [ {id: "4", name: "Audi"}, {id: "6", name: "Porsche"}, {id: "31", name: "Seat"}, {id: "32", name: "Skoda"}, {id: "5", name: "BMW"}, {id: "36", name: "Toyota"}, {id: "38", name: "Volkswagen"} ] 
const order = ['Volkswagen', 'Audi'];

let sortedResult = brands.sort((a,b) => {
  let index = order.indexOf(a.name)
  return index < 0 ? a.name.localeCompare(b.name) : order.indexOf(b.name) - index
})

console.log(sortedResult)

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

What is the best way to refresh a page during an ajax call while also resetting all form fields?

Each time an ajax request is made, the page should refresh without clearing all form fields upon loading Custom Form <form method='post'> <input type='text' placeholder='product'/> <input type='number&a ...

Trimming white spaces of array values in PHP can be achieved by using the array_map

Looking for a solution to trim white spaces from an array in PHP? Here's the scenario: $fruit = array(' apple ','banana ', ' , ', ' cranberry '); The desired outcome is to have an array with ...

Execute a zoom out action by pressing the (Ctrl) and (-) keys simultaneously in Javascript

I'm trying to figure out how to simulate a Ctrl - zoom out using Javascript. I've noticed that using the style zoom property or the transform property gives different results with white space in the corners, rather than the smooth zoom out effect ...

Is there a way to adjust user privileges within a MenuItem?

One of my tasks is to set a default value based on the previous selection in the Userlevel dropdown. The value will be determined by the Username selected, and I need to dynamically update the default value label accordingly. For example, if "dev_sams" is ...

The ENOENT error code 4058 occurred while attempting to create a new react application using

Every time I run the command npm create-react-app my-app, I encounter an error like this: npm ERR! code ENOENT npm ERR! syscall spawn C:\Windows\System32; npm ERR! path C:\Users\Administrator\Documents\th-wedding\templa ...

Displaying the chosen array in a Material UI Table within a React application does not show the desired checkboxes

After days of hard work and research, I finally figured out how to achieve what I needed. In my React App, I have a Material UI table that I want to load with pre-rendered checks in the DOM based on entries in a selected array. The selected array contains ...

What would the equivalent Javascript implementation look like for this Python code that decodes a hex string and then encodes it to base64?

Currently, I am facing the challenge of transferring code from a Python script that decodes and encodes a string using a series of decode() and encode() functions. In Python, the code appears as follows: import codecs input = '3E061F00000E10FE' ...

The Power of ReactJS Spread Syntax

Currently working with React. In the state, I have an array of objects. this.state = { team: [{ name:'Bob', number:23 }, { name:'Jim', number:43 }] } My issue arises when attempting to create a copy of the arr ...

Unforeseen outcomes arise when toggling expansion in JavaScript

I have a pop-out div at the top of my page that expands and closes on toggle. Also, when I toggle the pop-out div, it changes the top position of another div (a side pop-out menu). The issue is that the side pop-out menu should only appear when clicking ...

The most efficient method for handling a vast amount of data in NodeJS

My database consists of 4 million numbers and I need to quickly check if a specific number exists in it. Example of the database: [177,219,245,309,348,436,...] I initially tried using a MySQL table for this task, but it took a lengthy 1300ms just to chec ...

Using Kendo TabStrip to dynamically include HTML files as tabs

In the process of creating a web-part that mirrors a Kendo tabstrip, I've managed to integrate a simple ul with external html files linked to each relative li using JavaScript. The functionality works smoothly up until this point. However, my current ...

Unable to retrieve the parent element using jQuery

I am facing an issue with my html structure that is generated dynamically through a foreach loop. I have attempted to remove the entire <a> element by accessing it from its ACTIVE HYPERLINK. However, all my efforts seem to be in vain as I am unable t ...

Is the default behavior of Ctrl + C affected by catching SIGINT in NodeJS?

When I run my nodejs application on Windows, it displays ^C and goes back to the cmd prompt when I press Ctrl + C. However, I have included a SIGINT handler in my code as shown below: process.on('SIGINT', (code) => { console.log("Process term ...

Utilizing a child component in React to trigger a function on its sibling component

Trying to put this question into words is proving to be a challenge. I am wondering in React, if there is a way for a child component that is deeply nested (2 levels deep from the parent) to trigger a function on another component that it has a sibling rel ...

Can you explain the distinction between locating an element by its class name versus locating it by its CSS selector?

Class name: var x = document.getElementsByClassName("intro"); CSS selector: var x = document.querySelectorAll("p.intro"); I'm a bit puzzled, are there any distinctions between the two methods or are they essentially the same? ...

EJS failing to render HTML within script tags

Here is some code that I'm working with: <% // accessing content from a cdn api cloudinary.api.resources( { type: 'upload', prefix: '' }, (error, result) => { const assets = result.r ...

Receive information from a form and store it in an array

Struggling to figure out how to convert this into an array. I'm having trouble grasping the concept of taking input from a form and storing it in an array. In my project instructions, it clearly states: Do NOT save the input in variables and then tra ...

Encountering invalid parameters while attempting to utilize the track.scrobble service from the Last.Fm API in a Node.js application

After successfully completing the Last.Fm authentication process following the instructions provided here, I received the session key without any issues. However, my attempts to make an authenticated POST request to the track.scrobble method of the Last.Fm ...

Vue alerts and pop-ups will only show once

Utilizing vue ui to create a new project with Babel and Lint, I integrated dependencies vuetify, vuetify-loader, and vue-bootstrap. My goal was to have a simple 'open dialog' button that would reveal a dialog defined in a separate component file. ...

AngularJs Controller with explicit inline annotation

I usually inject dependencies using inline annotations like this angular.module('app') .controller('SampleController',['$scope','ngDependacy',sampleController]); function sampleController($scope,ngDependacy) { ...