Enhancing the performance of sortable array and object structures in Javascript

When working with objects in javascript and needing to maintain a specific sort order, key/value pairs cannot be used. Instead, utilizing an array with features like ES6 map is more suitable.

An example structure that could be used is shown below. The id is specified and all the items are enclosed within an array. This concept applies to the col blocks as well.

[
  {
    id: 21,
    items: [
      {
        col: 'name',
        data: {
          data1: 'hello',
          data2: 'world'
        }
      },
      {
        col: 'slug',
        data: {
          data1: 'hello',
          data2: 'world'
        }
      }
    ]
  },
  {
    id: 44,
    items: [
      {
        col: 'name',
        data: {
          data1: 'hello',
          data2: 'world'
        }
      },
      {
        col: 'slug',
        data: {
          data1: 'hello',
          data2: 'world'
        }
      }
    ]
  },
]

The Challenge

An issue arises with this method when it becomes necessary to search for specific identifiers such as finding id 44. In real scenarios, there could be numerous groups instead of just two, adding complexity. Similarly, there may be several columns within each group of items, requiring extensive searching.

Desired Code Structure

let result = get(44, 'slug', 'data2');

Regarding Performance

  • Does the provided structure ensure good performance?
  • How can efficiency be maintained without compromising performance?

Answer №1

Your method of retrieving data will not lead to significant delays. By scanning through each item and its sub-fields in a linear manner, you will encounter a complexity of O(m*n). This means that for every group, you need to check each column and extract the data by name (assuming this operation has an O(1) complexity). With 100 groups and 20 columns, the maximum number of operations is 2000, if you are accessing the very last item. This process should be reasonably fast, as it involves verifying if it's the correct item and discarding the rest.

If you find this approach too slow and require frequent lookups, you can enhance the efficiency of fetching data to O(1) by creating a lookup table from your data structure. This entails setting up a table with group IDs, column names, data keys, and corresponding values.

+----------+-------------+----------+-------+
| group id | column name | data key | value |
+----------+-------------+----------+-------+
|       21 | name        | data1    | hello |
|       21 | name        | data2    | world |
|       21 | slug        | data1    | hello |
|       21 | slug        | data2    | world |
|  etc...  |    etc...   |  etc...  | etc...|
+----------+-------------+----------+-------+

This can be represented using nested Maps:

const data = [ { id: 21, items: [ { col: 'name', data: { data1: 'hello', data2: 'world' } }, { col: 'slug', data: { data1: 'hello', data2: 'world' } } ] }, { id: 44, items: [ { col: 'name', data: { data1: 'hello', data2: 'world' } }, { col: 'slug', data: { data1: 'hello', data2: 'world' } } ] }, ];

const lookupTable = new Map();

data.forEach(group => {
  if (!lookupTable.has(group.id)) {
    lookupTable.set(group.id, new Map());
  }
  
  const groupLookupTable = lookupTable.get(group.id);
  
  group.items.forEach(column => {
    //only set the `data` object
    groupLookupTable.set(column.col, column.data);
  })
})

function get(id, col, data) {
  const group = lookupTable.get(id);
  
  if (!group) return;
  
  const columnData = group.get(col);
  
  if (!columnData) return;
    
  return columnData[data];
}


let result = get(44, 'slug', 'data2');

console.log(result)

When assigning the object to data, consider doing so at the end since it is more cost-effective than converting it into a Map or storing another object's memory for the same data. Additionally, the speed of looking up a key in an object should be equivalent to searching for it in a Map. Although plain objects can be used instead of Maps, a Map ensures consistency in key types at the very least.

Answer №2

Although the solution provided by @VLAZ may work well in various scenarios, here is an alternative approach.

function createLookup(items) {
    let lookupTable = {};

    items.forEach((row, y) => {
        if (!(row['id'] in lookupTable)) {
            lookupTable[row['id']] = {
                y: y,
                columns: {}
            };
        }

        row.items.forEach((col, x) => {
            lookupTable[row['id']].columns[col['column']] = x;
        });
    });

    return lookupTable;
}

This function will produce a lookup object structured like this:

21: {
  y: 0,      
  columns: {
    data1: 0
    data2: 1
  }
},
44: {
  y: 1,      
  columns: {
    data1: 0
    data2: 1
  }
}

Subsequently, another function can be utilized to retrieve the correct data from the original array based on x and y coordinates.

Update

The following method is now employed to fetch data:

function fetchItemData(items, lookupTable, rowId, column) {
  const columnIndex = lookupTable[rowId]['columns'][column];
  const rowIndex = lookupTable[rowId]['y'];

  return items[rowIndex]['items'][columnIndex];
}

let result = fetchItemData(data.rows, test, 28, 'meta_title');

console.log(result['data']);

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

Do Firefox and Chrome yield different results when using navigator.geolocation.getCurrentPosition()?

I need assistance with a code snippet that I have. It involves the following: navigator.geolocation.getCurrentPosition(function(position) { // do something }); However, I am encountering differences in the result returned between Chrome and Firef ...

Table borders disappear when loading PHP echoed tables with jQuery and Ajax

Currently, I am delving into the world of jQuery, PHP, AJAX, and MySQL. My objective is to retrieve a table from the MySQL server and exhibit it on a webpage. This involves two PHP files – one serves as the back-end script connecting to the database and ...

Is it possible to provide an offset to the raycaster in three.js?

I am currently working on developing a pool game using three.js. As part of the gameplay, I have incorporated a helper ruler that indicates the direction of the hit. This ruler is represented by an ArrowHelper and is positioned at y=0, which aligns with ...

How can I merge my two custom filters into a single, more efficient custom filter?

I have developed two custom filters that are quite similar. The only distinction between these filters is the array they utilize. Therefore, I am considering creating a single custom filter and passing an array as a parameter to it. The arrays I intend to ...

Dealing with mixed data types when parsing JSON using PHP's array and

Currently, I am attempting to extract information from JSON data to display on a fanpage I am developing. The JSON file I am working with can be found here. Upon inspection of the JSON link, you will notice that the structure follows a format of [{key:valu ...

How can I use VB codebehind in ASP to display a dialog box to the user asking for a yes or no response?

I am faced with a scenario where a user has chosen a product, the system has retrieved the product record, and the backorder flag has been set. I need to inquire if the user still wants to proceed with including the product in the order. However, I am stru ...

What is the best method to access nested objects in react-native when working with this.state?

I am working with a straightforward component, shown below: import React, { Component } from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default class Statistics extends Component { constructor(p ...

When working with JavaScript, it's important to note that any reference used outside of the catch block

Our JavaScript code includes a try...catch block that functions as follows: We import the customFile using: const ourCustomClassFile = require('./customFile'); In the customFile.js file, we have defined a function const sendErrorNotification ...

"Unleashing the Power of AngularJS: Implementing a Global Error Handler to Display and

When building my website, I have multiple Angular apps that require a global error handler to track and display alerts for errors with codes like 500 and 401. Here is what I have so far: In order to create a global error handler module, I've set up t ...

Is there a way to conceal a div that holds a full table when the table consists of only one row?

I am relatively new to working with JS and HTML. I have attempted to use the following function, but unfortunately, I am not seeing any results. Any assistance would be greatly appreciated. Below is the JavaScript code as well as the HTML div and table whe ...

Loading a Threejs model: "The CORS policy has blocked access to XMLHttpRequest from origin 'null' - How can I test this locally? Or should I simply upload it?"

Experimenting with three.js locally on a single HTML page, I am interested in exploring loading and manipulating 3D object files. Here is the code snippet that I am currently using: var loader = new THREE.AMFLoader(); loader.load( '. ...

What is the best way to incorporate an array of objects into the React state hook?

I have successfully retrieved data from the API in the specified format: { teamsregistered: [ { paid: false, _id: 602dea67451db71e71e4babd, name: 'MOH', mobile: '+919566879683', tag: 'JAR1NAH', __v: 0 }, { paid: false, _id: 6 ...

ajax with names that are alike

I've set up a text input field that searches for file names on my server. However, it currently requires an exact match to display the file. I'm looking for a solution that can show me files even if the input text isn't an exact match. Here ...

`Populating fields in Firebase``

I am currently in the process of transitioning from a Mongoose + Express app to using Firebase + Express. However, I am facing some challenges with populating related fields similar to how it is done in Mongoose. Is there a more efficient way to achieve th ...

Issue with v-model not updating data correctly when using switch and select dropdown in VueJS

I am developing a dynamic admin panel that includes a CRUD generator using Laravel and Vue. Within my table, I am asynchronously loading data from an API. One specific column in the table, called is_featured, needs to function as a switch. This will allow ...

Issue encountered while attempting to save a value in localStorage

I am encountering an issue while trying to save and read the value of a button in the panel. The error message I receive is - Unable to set property 'adl' of undefined or null reference. This is my first time working with localStorage, so I' ...

Error in typescript: The property 'exact' is not found in the type 'IntrinsicAttributes & RouteProps'

While trying to set up private routing in Typescript, I encountered the following error. Can anyone provide assistance? Type '{ exact: true; render: (routerProps: RouterProps) => Element; }' is not compatible with type 'IntrinsicAttribu ...

A guide to translating the centroid of an object in three.js during panning操作

Is there a way to adjust the centroid of an object's bounding box while panning? I've noticed that when I pan the object, the center point for rotation stays the same as it was before. Can anyone offer some guidance on how to address this issue? ...

Configuring the port number of the socketio connection in Heroku

I attempted to create a chat application using JavaScript and npm. After completing it to some extent, I deployed it to Heroku and encountered the error net :: ERR_CONNECTION_REFUSED in Chrome's developer tools. I suspect that Socket.io, Express, and ...

Add several additional views following an element within a View in Backbone

addDimensions: function (order_id, counter) { this.dimensionsView = new dimensionsView({ el: "#panel-boxes-" + order_id + "_" + counter, id: order_id, counter: counter }); $("#panel-boxes-" + order_id + "_1").append(this.dimensionsView.render().el) ...