Reordering an Array Based on Another Array’s Order in Javascript

So I had a problem, awhile ago, where I needed to reorder elements in an array based off of the order of another array. So I basically had to capture the order from one and apply it to another. In my case, both arrays had a common id field. However, with the model I have here, I was able to order additional arrays without the id field, if I needed to, which I did 🙂

Below is my code solution.

function getNewOrder() {
    //Get an identifier from the array you want to base the order on
    const newIds = newArrayOrder.map(x => x.id);
    
    //Get an identifier from the array you want to update
    const ids = arrayToOrder.map(x => x.id);
    
    //placeholder for order
    const order = [];
    
    //loop through the ids, pushing the arrayToOrder's index of the new order ids
    //We end up with an array of indexes
    for(let i = 0; i < ids.length; i++) {
      order.push(ids.indexOf(newIds[i]));
    }
    
    //reorder the array
    reorderIds(order, arrayToOrder);
}

//Preform the reordering
function reorderIds(order, arrayToOrder){
    //Get a copy of the array we want to change
    const temp = arrayToOrder.slice(0);
    
    //loop through the indexes
    //use the indexes to place the items in the right place from the copy into the original
    for(let i = 0; i < arrayToOrder.length; i++) {
      arrayToOrder[order[i]] = temp[i];
    }
}

 

Deep Photo Style Transfer

This really cool github project, called deep-photo-style-transfer, was shared with me awhile back.

It basically takes two images and merges them together very cleanly. Their code takes an approach to photographic style transfer that can take on a large variety of image content while preserving the reference style. Their research can be viewed here. Here are some pictures below of what it can do!

Check it out!

Javascript Cloning and Moving DOM Elements to Mouse Position

So I was working with dragula, a super easy to use drag and drop library. However, I ran into an issue where when a user clicks the dragging element, I wanted everything in the background to collapse. This messed up the dragging element’s position in relation to where the mouse’s location. In most cases when you drag and drop an element, it hovers wherever your mouse is located. In my case, when I shifted everything, the element I wanted to drag was no longer located where I clicked but rather it moved and hovered in the wrong spot with the wrong offset from my mouse. In using this library, I didn’t have access to changing their inner coding offset logic, so I needed to come up with my own fix. In the end, I decided to hide their floating mouse DOM element and create my own, that I had control over. The following code shows how to do just that!

Happy coding! Let me know if you have any comments or improvements.

//call this function when we want to initiate the listener for moving the mouse
//For instance, call this function once the user starts dragging an element
//requires an event and element to be passed.
function startMouseMove(e, element) {
    $('.my-background-content').css( 'display', 'none' ); //collapse background elements
    const container = $(element).find('.item-to-clone').clone().appendTo('.my-container'); //clone the element you want to hover around mouse
    $(container).attr('id', 'cursor_element'); //give the clone element an id so we can reference it later
    $('#cursor_element').css({'position': 'fixed', 'top': e.pageY, 'left': e.pageX}); //set clone element's position to mouse's position
    $document.on('mousemove', moveElement); //bind mouse event
}
 
function moveElement(e) {
    const y = e.pageY; //get y position
    const x = e.pageX; //get x position
    $('#cursor_element').css({'top': y, 'left': x}); //move the position of the element to match mouse, whenever mouse moves
}
 
//call this function when we want to stop the listener for moving the mouse
//For instance, call this function once the user drops a dragging element
function stopMouseMove() {
    $('#cursor_element').remove(); //delete cloned element
    $('.my-background-content').css( 'display', '' ); //un-collapse background elements
    $document.unbind('mousemove', moveElement); //unbind mouse event
}

Note that $document and JQuery must be declared/injected into the controller for this to work.

The above code requires JQuery, but you could easily use vanilla Javascript. Check this out for event help and this out for DOM selection.

Javascript Mousemove Scroll Event

Sometimes you just want the window to scroll when the user moves their cursor to the top or bottom of the page. For instance, some drag and drop events block out scrolling and it is difficult for users to drag their element where they need it to go without it. Wouldn’t it be nice if we could use something to detect where the mouse is and scroll for the user automatically? Well we can! The following code insert does just that! For it, I am using angularJs events and JQuery element selection but you can use vanilla javascript to do both of these. Check this out for vanilla javascript event help and this out for DOM selection.

//call this function when we want to initiate the listener for moving the mouse
//For instance, call this function once the user starts dragging an element
function startMouseMove() {
    $document.on('mousemove', scrollWindow);
}

function scrollWindow(e) {
    const y = e.pageY; //This collects details on where your mouse is located vertically
    const container = $('.my-container'); //Replace this with the element class(.) or id(#) that needs to scroll
    const buffer = 200; //You can set this directly to a number or dynamically find some type of buffer for the top and bottom of your page
    const containerBottom = container.offset().top + container.outerHeight(); //Find the bottom of the container
    const containerTop = container.offset().top; //Find the top position of the container
    const scrollPosition = container.scrollTop(); //Find the current scroll position
    const scrollRate = 20; //increase or decrease this to speed up or slow down scrolling

    if (containerBottom - y < buffer) { //If the bottom of the container's position minus y is less than the buffer, scroll down!
      container.scrollTop(scrollPosition + scrollRate);
    } else if (containerTop + y < buffer) { //If the top of the container's position plus y is less than the buffer, scroll up!
      container.scrollTop(scrollPosition - scrollRate);
    }
}

//call this function when we want to stop the listener for moving the mouse
//For instance, call this function once the user drops a dragging element
function stopMouseMove() {
    $document.unbind('mousemove', scrollWindow);
}

Note that $document and JQuery must be declared/injected into the controller for this to work.

Happy coding!

Structure of a Program

Here is a short read to refresh on how to best structure a C++ program.

 
Structure of a program – C++ Tutorials

The best way to learn a programming language is by writing programs. Typically, the first program beginners write is a program called “Hello World”, which simply prints “Hello World” to your computer screen. Although it is very simple, it contains all the fundamental components C++ programs have:

Simple AVL Tree in C++

An AVL tree is a binary search tree(BST) however, unlike binary search trees, an AVL tree (named after Georgy Adelson-Velsky and Evgenii Landis) is self balancing. So no matter how many nodes you insert into the tree, it will adjust it’s branches and ensure the tree is balanced at all times. Making sure the subtree heights only differ by at most 1. BSTs are great for segregating and storing data with a O(log n) search time. Downside with BST is that it can get weighted on one side and doesn’t have an restrictions to prevent it from getting skewed. By switching to an AVL, data is balanced in the tree and the search time is decreased to log n.

So it is more efficient in most cases to use the AVL tree, below is an example of how to code this in C++. Note that the AVL tree uses a lot of the same code the BST did from this post.

#pragma once

#include <iomanip>
#include <iostream>

using namespace std;

class AVL
{
public:
    AVL(){
        root = nullptr;
    }
    ~AVL(){
        destroy(root);
    }
    
    //My Node class for storing data, note how I add height
    struct Node{
        int data;
        Node *left;
        Node *right;
        int height;

        Node(int d){
            data = d;
            left = nullptr;
            right = nullptr;
            height = 0;
        }

        void updateHeight(){
            int lHeight = 0;
            int rHeight = 0;
            if (left != nullptr) {
                lHeight = left->height;
            }
            if (right != nullptr) {
                rHeight = right->height;
            }
            int max = (lHeight > rHeight) ? lHeight : rHeight;
            height = max + 1;
        }

    };

    void insert(int val){
        insert(val, root);
    }

    //Rotate a Node branch to the left, in order to balance things
    Node* rotateLeft(Node *&leaf){
        Node* temp = leaf->right;
        leaf->right = temp->left;
        temp->left = leaf;

        //update the Nodes new height
        leaf->updateHeight();

        return temp;
    }

    //Rotate a Node branch to the right, in order to balance things
    Node* rotateRight(Node *&leaf){
        Node* temp = leaf->left;
        leaf->left = temp->right;
        temp->right = leaf;

        //update the Nodes new height
        leaf->updateHeight();

        return temp;
    }

    //Rotate a Node branch to the right then the left, in order to balance things
    Node* rotateRightLeft(Node *&leaf){
        Node* temp = leaf->right;
        leaf->right = rotateRight(temp);
        return rotateLeft(leaf);
    }

    //Rotate a Node branch to the left then the right, in order to balance things
    Node* rotateLeftRight(Node *&leaf){
        Node* temp = leaf->left;
        leaf->left = rotateLeft(temp);
        return rotateRight(leaf);
    }

    //Function that checks each Node's left and right branches to determine if they are unbalanced
    //If they are, we rotate the branches
    void rebalance(Node *&leaf){
        int hDiff = getDiff(leaf);
        if (hDiff > 1){
            if (getDiff(leaf->left) > 0) {
                leaf = rotateRight(leaf);
            } else {
                leaf = rotateLeftRight(leaf);
            }
        } else if(hDiff < -1) {
            if (getDiff(leaf->right) < 0) {
                leaf = rotateLeft(leaf);
            } else {
                leaf = rotateRightLeft(leaf);
            }
        }
    }

private:
    Node *root;
    //Insert a Node (very similar to BST, except we need to update Node height and then check for rebalance)
    void insert(int d, Node *&leaf){
        if (leaf == nullptr){
            leaf = new Node(d);
            leaf->updateHeight();
        }
        else {
            if (d < leaf->data){
                insert(d, leaf->left);
                leaf->updateHeight();
                rebalance(leaf);
            }
            else{
                insert(d, leaf->right);
                leaf->updateHeight();
                rebalance(leaf);
            }
        }
    }

    //Same as BST
    void destroy(Node *&leaf){
        if (leaf != nullptr){
            destroy(leaf->left);
            destroy(leaf->right);
            delete leaf;
        }
    }
    
    //Get the difference between Node right and left branch heights, if it returns positive
    //We know the left side is greater, if negative, we know the right side is greater
    int getDiff(Node *leaf){
        int lHeight = 0;
        int rHeight = 0;
        if (leaf->left != nullptr) {
            lHeight =  leaf->left->height;
        }
        if (leaf->right != nullptr) {
            rHeight = leaf->right->height
        }
        return lHeight - rHeight;
    }
};

Let me know if you have any issues!