Order a collection of items in a 2D array using JavaScript

In my game, there is a inventory system that allows players to automatically sort items based on name, quantity, and type.

// Setting up the Inventory grid
var InventoryWidth  = 2;
var InventoryHeight = 4;

var Inventory = new Array(InventoryWidth);
for (var i = 0; i < InventoryWidth; i++) {
Inventory[i] = new Array(InventoryHeight);
}

// Adding Items and default quantities
Inventory[0][0] = "Potion";
Inventory[1][0] = 2;

Inventory[0][1] = "Elixir";
Inventory[1][1] = 9;

Inventory[0][2] = "Antidote";
Inventory[1][2] = 5;

Inventory[0][3] = "Ether";
Inventory[1][3] = 1;

// Function for sorting items
function Sort2D(array2D, byColumn, ascending) {

// Sorting logic goes here:
array2D.sort(function(a, b)
{
if(a[0] === b[0])
{
var x = a[byColumn].toLowerCase(), y = b[byColumn].toLowerCase();

return x < y ? -1 : x > y ? 1 : 0;
}
return a[0] - b[0];
});

}

// Sorting rows by first column: "name", setting to 1 will compare and sort the quantities instead
Sort2D( Inventory, 0, true);

// Displaying grid contents
var output = "";
for(var i = 0; i < InventoryHeight; i++) {
  
  if (i == 0) {
      output += " | name | own |";
    }
  
for(var j = 0; j < InventoryWidth; j++) {

if (j == 0) {
output += "\n"+i+"|";
}

output+=Inventory[j][i];

if (j >= Inventory[0].length-1) {
output += "|\n";
} else {
output += ", ";
}
}
}
console.log(output);

However, I am struggling to understand how to sort the grid like a table of items. I require the ability to sort the rows based on a selected column and also have the option to do it in either ASC or DESC order. How should I approach this?

Answer №1

To alphabetically arrange an array, the localeCompare method is used. Dealing with numbers requires special attention to avoid confusion; hence, it is important to convert variables appropriately before comparison.

function sortAlphabetically(a, b) {
    return String(a).localeCompare(b);
}

["cat", "apple", "dog", "beef"].sort(sortAlphabetically);
// -> ["apple", "beef", "cat", "dog"]

The issue may lie in the structure of your array. Currently, your array appears as follows:

var inventory = [
    ["Potion", "Elixir", "Antidote", "Ether"],
    [2, 9, 5, 1]
];

This structure lacks a clear association between items like "Potion" and their corresponding values, leading to potential issues. Adjusting the array to reflect a better format can improve sorting results.

var inventory = [
    ["Potion", 2],
    ["Elixir", 9],
    ["Antidote", 5],
    ["Ether", 1]
];

Sorting this revised array becomes simpler. Additionally, utilizing the .concat() method ensures data preservation by cloning the array for sorting purposes. By default, returning data in ascending order conforms to common practice.

function sort2D(array, byColumn, isDescending) {

    var sorted = array.concat().sort(function (a, b) {

        return typeof a[byColumn] === "string"
            ? sortAlphabetically(a[byColumn], b[byColumn])
            : a[byColumn] - b[byColumn];

    });

    return isDescending
        ? sorted.reverse()
        : sorted;

}

sort2D(inventory, 0);
// -> [ ["Antidote", 5], ["Elixir", 9], ["Ether", 1], ["Potion", 2] ]
sort2D(inventory, 0, true);
// -> [ ["Potion", 2], ["Ether", 1], ["Elixir", 9], ["Antidote", 5] ]
sort2D(inventory, 1);
// -> [ ["Ether", 1], ["Potion", 2], ["Antidote", 5], ["Elixir", 9] ]

Hopefully, this explanation proves helpful in addressing your concerns.

Update: Logging array information is simplified with the following code snippet:

var output = inventory
    .map(function (inv) {
        return "| " + inv.join(" | ") + " |";
    })
    .join("\n");
console.log("| name | own |\n" + output);

Update 2: Provided below is a method to sort the existing data in the array.

function sort2D(array, byColumn, isDescending) {

    // Step 1: Sort the specified section of the array.

    var preSort = array[byColumn].concat().sort(function (a, b) {

        return typeof a === "string"
            ? sortAlphabetically(a, b)
            : a - b;

    });

    if (isDescending) {
        preSort = preSort.reverse();
    }

    // Step 2: Create a new array with the sorted column.

    var sorted = [];
    sorted[byColumn] = preSort;

    // Step 3: Generate a map detailing the sorted order.

    var sortMap = {};
    preSort.forEach(function (item, i) {
        sortMap[array[byColumn].indexOf(item)] = i;
    });

    // Step 4: Manually sort remaining items within the array.

    array.forEach(function (info, i) {

        var copy = [];

        if (i !== byColumn) {

            info.forEach(function (item, j) {
                copy[sortMap[j]] = item;
            });

            sorted[i] = copy;

        }

    });

    // Step 5: Return the newly sorted array.

    return sorted;

}

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 most efficient way to calculate the sum of all the numbers lying between the endpoints

I am faced with a complex array The array looks like this: let arr = [[2, "OR", 22, 22, "OR", 22, 20], [300, "OR", 22, 300, "OR", 22, 22, "OR", 1], [1212, 2, "OR", 1]] My goal is to extract and ...

What is the process for triggering a function event on click (or any other function) within a browser's activation?

Some time ago, I was trying to figure out why the onclick event wasn't working when I clicked on a specific area of the browser. After consulting a guide, I discovered the issue and fixed it. It turns out that the problem was quite simple, and now I u ...

Implementing file change detection using view model in Angular

When using the input type file to open a file and trigger a function on change, you can do it like this: <input type="file" multiple="multiple" class="fileUpload" onchange="angular.element(this).scope().fileOpened(this)" /> The functi ...

Firestore data displaying as null values

Recently, I encountered CORS errors while polling the weather every 30 seconds in my program. Upon investigating, I discovered that the city and country were being interpreted as undefined. To fetch user data from my users' table, I utilize an Axios ...

Border color options for select boxes

Currently, I am working on my first Django-bootstrap project and dealing with a select box. I am trying to customize it so that when clicked, the border of the select box and its options turns yellow, which is working well. However, there is an additional ...

Utilizing PHP Variables in Ajax Calls: Transferring Data between JS and PHP

I've been struggling to grasp how to pass information from PHP to JavaScript and vice versa. I've spent an entire night trying to figure this out and would really appreciate it if someone could help me understand how to send two variables to an a ...

Loading external libraries in Angular2: A step-by-step guide

I'm currently working on incorporating a Datepicker in Angular 2, but I'm facing an issue where the library is not loading. This is causing a template parsing error stating 'material-datepicker' is not a recognized element: My System.c ...

Mastering the control of a camera in three.js using a combination of keyboard and mouse navigation techniques

I have been working on a 3D environment in WEB GL using three.js, previously using orbitcontrols.js as shown in this project: http://codepen.io/nireno/pen/cAoGI. Recently, I came across a different method of navigating the environment using the W, A, S, D ...

What is the best way to safely store a logged-in user on the client-side?

As I delve into creating a login system for my simple social media website where users can make posts and view feeds from fellow followers, I've successfully implemented user login. Upon logging in, I'm able to retrieve the user's credential ...

Ways to clear dropdown selection in Vue based on a specific condition?

I am currently developing a dropdown menu for selecting visit status options, which include "pending," "canceled," "rejected," and "approved." In the case of an approved visit status, I would like the dropdown selection to only display the options for "can ...

PHP redirect malfunctioning, yet still functioning?

After making some changes to the structure of my website, I seem to have broken the script somehow. When a user fills out a form correctly, they should be redirected to the appropriate page. However, the page just hangs. Strangely, the form works fine when ...

Interact with elements on a dynamically loaded webpage using Selenium WebDriver in Java

I am faced with a challenge of clicking on a specific element on a dynamically loaded page, where the web element is generated as we scroll down the page, similar to the setup on a Jabong webpage. Here is the code I tried on the Jabong webpage: WebDrive ...

Dynamic allocation of memory for an array of structures using malloc

My goal is to dynamically create an array of structs. It seems to work fine with small sizes, but the program crashes later with a segmentation fault. When I use a large ipt_size, the program crashes quickly with nonsense numbers, leading me to believe tha ...

Event delegation will be ineffective when the target element is nested within another element

After receiving a recommendation from my colleagues on Stackoverflow (mplungjan, Michel), I implemented the event delegation pattern for a comment list. It has been working well and I am quite excited about this approach. However, I have encountered an iss ...

Can anyone guide me on saving an array to local storage, retrieving its contents, and populating them into a select element?

I have written code to retrieve an array and add its elements to a select object. Check it out: var select = document.getElementById('select'); var theArray = localStorage.getItem("array") JSON.parse(theArray) if (theArray != null){ f ...

Can you extract debugging details from an ajax preflight inquiry?

I am currently working on a JavaScript project that involves making an AJAX request. However, I am encountering issues with the preflight OPTIONS call for this request failing. To provide some transparency to the user, I would like to display debug infor ...

What is the best way to fill a sub-document following a $geoNear query?

I'm currently working with NodeJs and Mongoose to create a feature that lists nearby deals. Deal.db.db.command({ "geoNear": Deal.collection.name, "near": [23,67], "spherical": true, "distanceField": "dis" }, function (err, docum ...

Is it feasible to have unique popups for individual textbox edits?

I am experiencing a problem with a popup in Asp.net while using AJAX modalpopup extender. I am wondering if it is feasible to display one type of popup when the user modifies certain textboxes, and another type of popup for the remaining textboxes. I beli ...

Using jQuery to create a flawless animation

I am currently working on an animation project, and I have shared my progress on jsfiddle. Below is the code snippet I have utilized: /* JavaScript: */ var app = function () { var self = this; var allBoxes = $('.box&apos ...

Creating an array of data from JSON using JavaScript and displaying it in a chart using ApexChart

I am attempting to generate a chart displaying the value of Bitcoin in Euro. The data is fetched from JSON and converted into an array for the ApexChart series data (ApexData['xbtToEuro']) along with a list of dates. Despite my console indicatin ...