Rearrange the elements in an array containing objects

I am working with an array of objects:

const array = [
  {
    id: "5a2524432b68c725c06ac987",
    customOrder: 1,
    name: "One",
  },
  {
    id: "5a2524432b68sgs25c06ac987",
    customOrder: 2,
    name: "Two",
  },
  {
    id: "5a252wfew32b68c725c06ac987",
    customOrder: 3,
    name: "Three",
  },
  {
    id: "5a25gffe32b68c725c06ac987",
    customOrder: 4,
    name: "Four",
  },
  {
    id: "5a2524432b68c725c06acfee7",
    customOrder: 5,
    name: "Five",
  },
  {
    id: "5a2524432b68c725c06ac556",
    customOrder: 6,
    name: "Six",
  },
]

If I update the customOrder property of one object and need to adjust the customOrder values of the other elements accordingly, for example changing index 2 to have a custom order of 4, resulting in:

const array = [
  {
    id: "5a2524432b68c725c06ac987",
    customOrder: 1,
    name: "One",
  },
  {
    id: "5a2524432b68sgs25c06ac987",
    customOrder: 2,
    name: "Two",
  },
  {
    id: "5a25gffe32b68c725c06ac987",
    customOrder: 3,
    name: "Four",
  },
  {
    id: "5a252wfew32b68c725c06ac987",
    customOrder: 4,
    name: "Three",
  }
  {
    id: "5a2524432b68c725c06acfee7",
    customOrder: 5,
    name: "Five",
  },
  {
    id: "5a2524432b68c725c06ac556",
    customOrder: 6,
    name: "Six",
  },
]

I'm pondering over using methods like array.slice() or possibly utilizing lodash's _.putAt(), but I am exploring simpler approaches to achieve the desired outcome.

Answer №1

Follow these four steps to achieve it:

  1. Utilize Array.findIndex() to find the entry with the same value as the one you want to update at the specified index.

  2. Update the value of this entry to match the value of the item at that index.

  3. Then, replace the item at the given index with the new value.

  4. Lastly, swap the items. If there isn't an item with the new value, sort the array to ensure the item is in the correct position.

This method alters the original array:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

const swap = (arr, x, y) => [arr[x], arr[y]] = [arr[y], arr[x]];

function setOrder(arr, idx, value) {
  const idx2 = arr.findIndex(x => x.customOrder === value);
  if (idx2 >= 0) arr[idx2].customOrder = arr[idx].customOrder;
  arr[idx].customOrder = value;
  
  if (idx2 >= 0) swap(arr, idx, idx2);
  else arr.sort((a, b) => a.customOrder - b.customOrder);
  return arr;
}

setOrder(array, 2, 4);
console.log(array);

setOrder(array, 2, 10);
console.log(array);

This approach keeps the original array intact:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

const swap = (arr, x, y) => [arr[x], arr[y]] = [arr[y], arr[x]];

function setOrder(arr, idx, value) {
  const out = [...arr];
  const idx2 = out.findIndex(x => x.customOrder === value);
  if (idx2 >= 0) out[idx2] = { ...out[idx2], customOrder: out[idx].customOrder };
  out[idx] = { ...out[idx], customOrder: value };
  
  if (idx2 >= 0) swap(out, idx, idx2);
  else out.sort((a, b) => a.customOrder - b.customOrder);
  return out;
}

console.log(setOrder(array, 2, 4));
console.log(setOrder(array, 2, 10));

Answer №2

To easily remove an item at a specific index and move it to a new index, you can utilize the splice method. Then update the order of items in the array by using customOrder with the help of forEach

(If you prefer not to modify the original array, you can create a copy using spread syntax and then use the map method)

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

function updateOrder(input, index, newIndex) {
  let copy = [...input];
  const removed = copy.splice(index, 1);
  copy.splice(newIndex, 0, removed[0]);
  return copy.map((a, i) => ({ ...a, customOrder: i+1 }))
}

console.log(updateOrder(array, 2, 3))

By allowing mutation:

const array = [{id:"5a2524432b68c725c06ac987",customOrder:1,name:"One",},{id:"5a2524432b68sgs25c06ac987",customOrder:2,name:"Two",},{id:"5a252wfew32b68c725c06ac987",customOrder:3,name:"Three",},{id:"5a25gffe32b68c725c06ac987",customOrder:4,name:"Four",},{id:"5a2524432b68c725c06acfee7",customOrder:5,name:"Five",},{id:"5a2524432b68c725c06ac556",customOrder:6,name:"Six",},]

function updateOrderMutation(input, index, newIndex) {
  const removed = input.splice(index, 1);
  input.splice(newIndex, 0, removed[0]);
  input.forEach((a, i) => a.customOrder = i + 1)
  return input;
}

console.log(updateOrderMutation(array, 2, 3))

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 retrieve all SVG objects within a specific area in an Angular application?

I am currently developing an SVG drawing application and have implemented a tool that enables users to select all shapes within a rectangular area. However, I am facing the challenge of detecting the SVG shapes located underneath the selected rectangle. ...

Encountering an issue with React npm causing errors that I am unable to resolve

Hey there, I'm a newbie to React. After setting everything up, I encountered an error after running "npm start." Can anyone help me figure out how to fix this? Thanks in advance! Click here for image description ...

Using JQuery to automatically scroll and anchor to the bottom of a dynamically populated div, but only if the user doesn't

I am attempting to achieve the functionality of automatically scrolling to the bottom of a div with the ID #chat-feed. The overflow for this div is set to auto, and I want it to remain at the bottom unless a user manually scrolls up. If they do scroll up, ...

Ways to retrieve the current state within a function after invoking the setState method

I'm currently working on a function to store the blogPost object in a document within my Firestore database. The process I have in mind is as follows: Click on the SAVE button and initiate the savePost() function The savePost() function should then ...

Tips for determining if an array of objects, into which I am adding objects, contains a particular key value present in a different array of objects

I've been working on this and here is what I have tried so far: groceryList = []; ngOnInit() { this._recipesSub = this.recipesService.recipes.subscribe((receivedData) => { this.loadedRecipes = receivedData.recipes; }); } onCheckRecipe(e) { ...

Having trouble updating the URL path with the $location service in Angular

I'm facing a challenge in updating the URL path using the $location.url service, as it's not reflecting the changes correctly. For instance, my current URL path is http://localhost:64621/module/commercial/#/company/98163780-4fa6-426f-8753-e05a6 ...

Display only alphabetic characters in the text field

I have a jQuery function that I am working on: $('#contact_name').on('input', function() { var input=$(this); var re =/^[A-Za-z]+$/; var is_email=re.test(input.val()); if(is_email) { } else { } }); This function is targeted at the fol ...

When executing a function, the previous React state continues to linger

Why is the updateUser() function only updating the last user instead of all users despite using useCallback and including users as a dependency? The expected output after clicking the update button should be: {"id":1,"name":"John& ...

Creating a Python server for an Angularjs application and capturing user input

Can you offer me some assistance, whether it's just a hint or a useful tip that could improve my current approach? I have created a series of forms using HTML and AngularJS. Each form collects input data from users, which is then stored in a JSON str ...

Using Vue.js to pass a variable from a parent component to a child component

Parent component: ShowComment Child component: EditComment I'm attempting to pass the value stored in this.CommentRecID to the child component. In the template of ShowComment, I have included: <EditComment CommentRecID="this.CommentRecID" v-if= ...

Leveraging Next.js ISR to pass extra information to the getStaticProps function from the getStaticPaths

Inside SingleBlogPost.jsx, the code for generating blog pages by their slug is as follows: export async function getStaticPaths() { const res = await fetch("http://localhost:1337/api/posts"); let { data } = await res.json(); const paths = data.map(( ...

Struggling to troubleshoot an error - Invalid key Token '{' found at column 2

I am encountering a debugging issue that I can't seem to resolve. form-field.html <div class='row form-group' ng-form="{{field}}" ng-class="{ 'has-error': {{field}}.$dirty && {{field}}.$invalid }"> <label cla ...

Retrieve the computed value of a cell in an Excel spreadsheet using Node.js

Utilizing node.js in tandem with the exceljs module to process my Excel sheets. Writing values into specific cells while others already contain formulas. Seeking a method to trigger those formulas and programmatically store the resultant values in the she ...

Best practices for loading and invoking Javascript in WordPress child themes

After spending countless hours searching for a detailed tutorial on how to properly incorporate Javascript into a WordPress website, I came up empty-handed. Running the Genesis Framework with a child theme on my localhost, I am eager to add a fullscreen b ...

Enabling real-time notifications through Express 4 middleware with socket.io integration

I am in the process of developing a real-time notification system utilizing socket.io. Here is the current server-side code I have implemented: bin/www: var app = require('../app'); var server = http.createServer(app); var io = app.io io.attac ...

Tips for executing a function in jQuery when a Pop up appears

I am currently utilizing the AjaxToolKit:ModelPopUpExtender to generate a popup within an asp.net application. At first, the asp:Panel (which holds the content of the popup) is set as <asp:Panel ID="PanlUpdate" runat="server" CssClass="Popup" align="c ...

Loop through the input fields using ng-repeat while maintaining consistent values for each iteration

I am facing an issue with my ng-repeat loop where I have a comment input inside it. The problem is that when I start typing in the first input, the text appears simultaneously in all other inputs as well. I have tried adding a unique ID but it didn't ...

Angular JS is throwing an error because it cannot recognize the property 'push' of undefined

Would like to automatically update the div using $scope.push encountering an issue: Error: Cannot read property 'push' of undefined Here are my JSON and JavaScript snippets: JSON {"records":[{"total":"156000"}]} JavaScript $scope.plusCar ...

Using Next-auth.js: Redirecting from getServerSideProps to a specific callback URL - How can it be done?

Hey, I've been working on implementing authentication with the NextAuth library in my Next.js application. While following the documentation, I encountered a situation that wasn't covered. I'm attempting to create a 'route guard' o ...

JavaScript - Two tables shown in parallel

Beginner coder seeking assistance! I am currently working on an application with two user input fields placed adjacent to each other. Clicking parse buttons next to these fields generates two separate tables. However, I need these tables to be displayed si ...