Rearrange the order of elements within an array and move elements around within it

I am looking to select an element from an array, relocate it to a different index, and then shift the elements in-between by 1 position. Consider this as drag-and-drop functionality, where if the starting index (from) is less than the destination index (to), then I want the shift to be towards the left; otherwise, it should be towards the right. Input:

let data = [ 0, 1, 2, 3, 4, 5, 6 ]

Task1:

insertAndShift(data, 0, 3): Select the element at index 0, shift indexes 1, 2, 3 to the left, and then insert the index 0 at position 3.

Expected Output:

[ 1, 2, 3, 0, 4, 5, 6 ]

Task2:

insertAndShift(data, 3, 0): Take the element at index 3, shift indexes 0, 1, 2 to the right, and then insert the element at index 3 into position 0.

Expected Output:

[ 0, 1, 2, 3, 4, 5, 6 ]

I attempted this methodology:

Referencing Rotating an array in place, although the code seemed flawed (temp variable undefined + incomplete result + potential functioning only for Right shifts):

insertAndShift(data, from, to)
{
    if(from < to)
    {
        // rotate in between - LEFT

    }
    else
    {    
        // swap elements
        let temp = data[from];
        data[from] = data[to];
        data[to] = temp;

        // rotate in between - RIGHT
        let newData = this.rotate(data.slice(to, from - 1), 1)

        let result = [];
        result.push(data.slice(0,1));
        newData.map((element) => result.push(element))
        for(let i = from+1; i < data.length; i++)
        {
            result.push(data[i]);
        }

        this.setState({data: result})
    }
}

rotate(arr, k) {
    var l = arr.length;
    arr = this.reverseArr(arr, 0, l - 1);
    arr = this.reverseArr(arr, 0, k - 1);
    arr = this.reverseArr(arr, k, l - 1);
    return arr;
}

reverseArr(arr, left, right) {
    while (left < right) {
        var temp = arr[left];
        arr[left] = arr[right];
        arr[right] = temp;
        left++;
        right--;
    }
    return arr;
}

Similarly, referring to Javascript (dynamic) insert into array, then shift all elements underneath +1, which seems to output just one item:

else
{
    let result = data.splice(to, 1, data[from]);
    this.setState({allTasksArray: result})
}

What would be the proper approach to achieve both Left and Right shifts?

Answer №1

If you need to rearrange elements in an array, you can utilize Array.prototype.splice. This method allows you to remove an element and insert it at a specific index with ease:

function moveElement(arr, currentIndex, newIndex) {
    let removedElement = arr.splice(currentIndex, 1)[0]; // remove the element from 'currentIndex'
    arr.splice(newIndex, 0, removedElement);            // insert it at 'newIndex'
}

let numbers = [7, 8, 9, 10, 11];
moveElement(numbers, 1, 3);
console.log("[" + numbers + "]");

Answer №2

The provided answer is effective, but it lacks detailed explanation. For those seeking a more in-depth solution that breaks down the process, I have crafted the following:

const insertAndShift = (arr: number[], to: number, from: number) => {
  let newArray: number[] = [];
  const fromItem = arr[from];
  if (from > to) {
    const startToTo = (to > 0) ? arr.slice(0, to) : [];
    const toToFrom = arr.slice(to, from);
    const fromToEnd = arr.slice(from + 1, arr.length);
    newArray = newArray.concat(startToTo, [fromItem], toToFrom, fromToEnd);
  }
  if (to > from) {
    const startToFrom = (from > 0) ? arr.slice(0, from) : [];
    const fromToTo = arr.slice(from + 1, to + 1);
    const toToEnd = arr.slice(to + 1, arr.length);
    newArray = newArray.concat(startToFrom, fromToTo, fromItem, toToEnd);
  }
  return newArray;
};

const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

console.log(insertAndShift(array, 9, 0));
console.log(insertAndShift(array, 5, 1));

Answer №3

Check out this technique: Array.prototype.copyWithin().

A more efficient method to achieve this is through an in-place approach:

function shiftAndInsert(data, src, dest) {
    if (src === dest)
        return;

    let temp = data[src];
    if (src < dest) {
        data.copyWithin(src, src + 1, dest + 1);
    } else /* if (src > dest) */ {
        data.copyWithin(dest + 1, dest, src);
    }
    data[dest] = temp;
}

let data = [0, 1, 2, 3, 4, 5, 6];

shiftAndInsert(data, 0, 3);
console.log("[" + data + "]");

shiftAndInsert(data, 3, 0);
console.log("[" + data + "]");

Here's a visual representation of the process:

Case 1 (src < dest):
[..Sabcd..]
    ////       // data.copyWithin(src, src+1, dest+1);
[..abcdd..]
[..abcdS..]    // data[dest] = temp;

Case 2 (src > dest):
[..abcdS..]
    \\\\       // data.copyWithin(dest+1, dest, src);
[..aabcd..]
[..Sabcd..]    // data[dest] = temp;

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 enhance this current array with additional submenus?

Code for current array: function fetch_menu($menu = array(), $ulclass = '', $is_main_menu = false) { global $menu_selected; $output = ''; if (empty($menu)) { return $output; } $output .= '<ul' ...

Express form validation router encountering abnormal behavior

My code includes a router.post that uses ajax to validate input in a form: if(req.body.firstname === '' || req.body.firstname !== req.body.firstname.match(/\D+/g)[0]) { console.log('AJAX ERROR: Firstname is empty and/or contains a nu ...

Can you explain what findDOMNode is and why it is no longer supported in StrictMode within the console?

I attempted to create a count-up feature using React visibility sensor and React count up, but encountered an error in the console. Is there a correct solution to this issue? Caution: The use of findDOMNode is deprecated in StrictMode. This method was uti ...

Implementing shallow routing with the Next.js 13 framework while having appDir functionality activated

Previously in Next 13 (or with appDir disabled), you could achieve the following: const MyComponent = () => { const router = useRouter(); const toggleStatic = () => { if (router.query.static) { router.push(router.pathname, router.pa ...

JQUERY inArray failing to find a match

I'm at my wit's end working with inArray and I'm really hoping for some help. I am using AJAX to fetch userIDs from my database, which come through as a JSON-encoded array. However, no matter what I try, I always get a -1 when trying to mat ...

Stop unauthorized access to PHP files by utilizing AJAX

Is there a way to prevent direct access to a specific PHP file named prevented.php? My approach involves a main file called index.php, which generates and stores a token in a $_SESSION variable. Additionally, there is another file called def.php that is ac ...

I am looking to transform CSV data into XLSX file format, upload it to AWS, and obtain the corresponding URL

I am currently in the process of converting a JSON file to CSV. My next step is to convert this CSV file to XLSX data and upload it to AWS to retrieve the link. Convert CSV to XLSX const xlsxFilePath = 'path/to/transaction_data.xlsx'; await csvto ...

Oops! The specified vue-router route name cannot be found

My issue involves a vue component with a method that includes a router push attempting to navigate to another vue component: GetAnimal.vue: ... this.$router.push({ name: "/viewanimal", }); ... The routing mapping is set up like this: router.js: { ...

Is it possible to integrate the screenfull JavaScript library into the Next.js framework?

Attempting to utilize Dynamic Importing in Nextjs for incorporating the screenfull library has proven unsuccessful. import dynamic from "next/dynamic" import screenfull from 'screenfull'; const Screenfull = dynamic(()=>{return import ...

Ways to set values for attributes

I am seeking guidance on how to set values for the properties foo and greetingMessage App.vue: <template> <img alt="Vue logo" src="./assets/logo.png"> <HelloWorld msg="Welcome to Your Vue.js App"/> < ...

Combining Array Elements to Create Overlapping Images in JavaScript

My goal is to create a planner where users can choose a wallpaper based on the season. Right now, I'm focusing on fall, and when you click on fall, you can see all the different wallpapers (each URL from my array is displayed). However, once the alert ...

unable to load variables in google extension due to technical difficulties

I'm encountering an error even though I've already loaded the DOM. I have no idea how to fix this issue and I've been sitting here for hours trying to troubleshoot. The error message I'm getting is: btncheck.js:10 Uncaught TypeError: C ...

Utilizing AJAX in Wordpress to Dynamically Update HREF Links

My website now has AJAX functionality, and you can see a live example at www.mathewhood.com. I am interested in changing the URL format when clicked from To something like , without the /sitefiles/ for security reasons. Below is my code. If anyone is ex ...

Bug in ExtJS 4 causing the clickrepeater to be disabled when using the datepicker

I've developed a custom subclass of the DatePicker class. Within the update() method, I have implemented logic to disable the prevRepeater if the current month matches the month of the minDate property: me.prevRepeater.setDisabled(me.minDate &&am ...

How do I connect TypeORM to multiple databases?

I am faced with the challenge of creating tables in two different databases using TypeORM. Each table is associated with a specific database through the use of the @Entity decorator. However, I encounter an error stating that user x does not have write acc ...

Error encountered when attempting to send ajax request to specified http endpoint using Cordova version 10

I've been struggling to successfully send JSON data to an HTTP URL (although I was able to successfully send the same data to an HTTPS URL). These are my current settings: config.xml <access origin="*" /> <allow-intent href="ht ...

The functionality of $watch in AngularJS is not meeting the desired outcomes

Within my controller, I am looking to receive notifications when the value of a certain variable changes. Specifically, I want a function to be triggered whenever this variable is updated. To achieve this, I am utilizing the $watch method in AngularJS. Her ...

What is the best way to have a variable adjust each time a coin is inserted until it reaches a specific value?

I have developed a unique coin box that recognizes the value of each coin inserted. Users can now pay for a service that costs 2.0 € by inserting coins of various denominations such as 2.0 €, 1.0 €, 0.50 €, 0.20 €, and 0.10 €. In my react-nati ...

Content Security Policy: The website's security measures prevented a resource from being loaded

Recently, I added the Google Sign-In button to my ReactJS web client. However, I encountered an issue where after a successful sign-in, the page did not redirect back from "https://accounts.google.com/..." to my web-client URL, which is http://localhost:50 ...

Whenever I execute the 'ng serve' command, I encounter an issue with ineffective mark-compacts close to the heap limit, resulting in an allocation failure and a JavaScript

I'm currently using Angular 9 and Node.js 12. When I input ng serve, I encounter the following problem: C:\Users\homz\my-app>ng serve 93% after chunk asset optimization SourceMapDevToolPlugin vendor.js generate SourceMap <--- ...