What is a creative way to store and organize ids along with their sub ids in an object without relying on arrays?

Currently, I am faced with the challenge of sending data to the server that contains multiple ids with sub ids. I have been utilizing arrays to handle this, but the repetitive use of find() and findIndex() functions in the DOM (specifically with Vue) is starting to become cumbersome. I wonder if there is a more direct way to access ids, allowing me to simply check or retrieve them using something like order[id][subid].

At the moment, my data structure looks like this:

let data = {
    orders: [
        { order_id: 4, items: [{ item_id: 6 }, { item_id: 7 }, { item_id: 8 }] },
        { order_id: 1, items: [{ item_id: 1 }, { item_id: 2 }, { item_id: 3 }] },
    ];
}

For instance, when I need to check if an item within an order is selected, I have to go through the following steps:

function check(order_id, item_id) {
    let order_i = data.orders.findIndex((o) => o.order_id == order_id);

    if (order_i != -1) {
        let item_i = data.orders[order_i].items.findIndex((o) => o.item_id == item_id);
    }

    if (item_i != -1) {
        return true;
    } else {
        return false;
    }
}

I am looking for a more efficient alternative, such as:

let data = {
    orders: {
        4: {6:'',7:'',8:''},
        1: {1:'',2:'',3:''}
    }
}

With this structure, I could simply use

data.orders?.[order_id]?.[item_id]
for quick access. However, I am unsure if this is the best approach. Are there any other structures I could use that do not involve arrays?

Answer №1

In my opinion, the ideal data structure for your needs would be a Map. A Map allows you to store key-value pairs and access the value of a specific key in constant time, making it much more efficient than searching through a list. The methods set(key, value) and get(key) are essential for working with a Map.

If you plan on storing all orders in this structure, using the order ID as the index in an array would be the most efficient approach. You could also use a Map for orders that are not sequential, along with a separate Map for items. If orders typically contain a small number of items, using an Array for that purpose should suffice.

For further information, check out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

Answer №2

Outlined below is a potential method to accomplish the specified goal.

Code Snippet

// function to convert data into the desired format
const convertData = obj => ({
  orders: obj?.orders?.reduce(      // using ".reduce()" to loop through orders
    (acc, {order_id, items, ...rest1}) => (   // convert each item in the array into key-value pairs
      acc[order_id] ??= {},
      acc[order_id] = {...rest1},
      acc[order_id].items = items.reduce(     // iterate through items
        (ac2, {item_id, ...rest2}) => (  // convert into key-value pairs
          ac2[item_id] ??= {},
          ac2[item_id] = {...rest2},
          ac2
        ),
        {}    // this could be replaced with new Map() for map usage instead of object
      ),
      acc
    ),
    {}        // this could be replaced with new Map() for map usage instead of object
  )
});

// NOTE: If using "new Map()", please use ".get()" and ".set()" for access and modification.

const data = {
  orders: [{
    order_id: 4, otherOrderProps: 'otherOrderValues1',
    items: [{
      item_id: 6, otherItemProps: 'a6'
    }, {
      item_id: 7, otherItemProps: 'a7'
    }, {
      item_id: 8, otherItemProps: 'a8'
    }]
  }, {
    order_id: 1, otherOrderProps: 'otherOrderValues2',
    items: [{
      item_id: 1, otherItemProps: 'a1'
    }, {
      item_id: 2, otherItemProps: 'a2'
    }, {
      item_id: 3, otherItemProps: 'a3'
    }]
  }]
};

console.log('converted data:\n', convertData(data));

console.log(
  '\n\nchecking for order: 1, item: 2\n',
  convertData(data)?.orders?.[1]?.items?.[2] ?? 'not-found'
);

console.log(
  '\n\nchecking for non-existent order: 3, item: 2\n',
  convertData(data)?.orders?.[3]?.items?.[2] ?? 'not-found'
);
.as-console-wrapper {
  max-height: 100% !important;
  top: 0
}

Explanation

Additional comments have been provided within the code snippet.

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

Is there someone who can explain to me the process behind this?

(function(ng, app){ app = angular.module('app', []); app.config(function($provide) { $provide.constant('town', 'Burlington'); }); app.constant('name', 'Rob F.'); app.controlle ...

What is the best way to add a hyperlink to a cell in an Angular Grid column

I need help creating a link for a column cell in my angular grid with a dynamic job id, like /jobs/3/job-maintenance/general. In this case, 3 is the job id. I have element.jobId available. How can I achieve this? Here is the code for the existing column: ...

Guide to sending an array to Jade for rendering using NodeJS and ExpressJS

Coming from a background in "functional" programming languages like PHP, Lua, and C, I am currently facing a challenging learning curve as I transition to the MVC model used in NodeJS. I've been struggling to display a simple MySQL array in Jade and ...

Creating a standard login.js file for seamless integration with nightwatch.js testing

When creating tests for my web application, I need to first simulate a login before proceeding with the rest of the tests to access inner pages. Currently, I am in the process of refactoring the code so that I can create an 'include' for common f ...

React- hiding div with hover effect not functioning as expected

I'm having trouble using the :hover feature in CSS to control the display of one div when hovering over another, it's not functioning as expected. I've successfully implemented this on other elements, but can't seem to get it right in t ...

What is the best way to access an error's body in order to retrieve additional error message details when using the forge-api with nodejs?

I'm struggling to retrieve the body content when an error is returned from the API request. I've attempted creating a bucket with uppercase letters, but all I receive is an error object with statusCode = "400" and statusMessage = "BAD REQUEST". ...

Having trouble accessing a DOM element within a Vue component while using vanilla JavaScript

I am attempting to dynamically update data from a Vue component using jQuery in a Webpack project. Below is the code snippet: <template> <div id="container"> <slot>show string!!</slot> <div id="s_container"&g ...

Guidelines for leveraging AngularJS Decorators to deactivate a button within an Html document

Currently, I am utilizing the blur admin theme and exploring the possibility of using decorators to hide a button without directly modifying the HTML. Despite my efforts, I have been unable to successfully conceal the button. Can someone provide guidance o ...

if statement not recognizing data returned from PHP function

I'm currently working with a function that is being used for an AJAX query: var formData = $(this).serialize(); //store form names and values in an array called 'formData' $.get('filtertest.php',formData,processData); //jQ ...

Intercepting HTTP requests on specific routes with Angular 4+ using an HTTP Interceptor

I've developed an HTTP_INTERCEPTOR that needs to function on certain routes while excluding others. Initially, it was included in the main app module file. However, after removing it from there and adding it to specific modules, the interceptor conti ...

Incorporate npm libraries into vanilla JavaScript for HTML pages

Attempting to incorporate an npm package into plain JS/HTML served using Python and Flask. <script type="module"> import { configureChains, createClient } from "./node_modules/@wagmi/core"; import { bsc } from "./nod ...

When a web page is translated using Google Translate, Vue components may cease to update properly

When Vue components on pages are translated using Chrome's translate feature, the components stop re-rendering and updating the view. For example, if you try to translate https://v2.vuejs.org/v2/guide/#Handling-User-Input in Chrome to a different lan ...

Encountering issues with ASP.NET WebAPI: When using $.ajax, a 404 error occurs, while using $.getJSON results in an Uncaught

Currently, I am developing an ASP.NET web API with a C# project that I am attempting to call from JavaScript. Below is the snippet of my JavaScript code: function LoadGraph() { var file = document.getElementById("file-datas"); if ('files' in fi ...

Ways to correct inverted text in live syntax highlighting using javascript

My coding script has a highlighting feature for keywords, but unfortunately, it is causing some unwanted effects like reversing and mixing up the text. I am seeking assistance to fix this issue, whether it be by un-reversing the text, moving the cursor to ...

Building a single page web application using TypeScript and webpack - a step-by-step guide

For a while now, I've been working on single page applications using Angular. However, I'm interested in creating a single page application without utilizing the entire framework. My goal is to have just one .html file and one javascript file, w ...

Error encountered while parsing Node.js code for MySQL query execution

I am encountering an error message from Node that reads: Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TIMESTAMPDIFF(second, entered_at, c ...

Select a picture at random from a directory

As a student embarking on an art project, I am in the process of selecting one out of 500 images to display on a webpage. My coding knowledge is quite limited, primarily focused on HTML and CSS, with only a basic understanding of JavaScript. I am encounter ...

Creating a webpage with a left panel and draggable elements using JavaScript/jQuery

As someone new to Javascript/jQuery, I have been given the task of creating a web page with elements in a "pane" on the left side that can be dragged into a "droppable" div area on the right side. The entire right side will act as a droppable zone. I am u ...

ways to verify ng-if post modification occurrence

Currently, my project is utilizing Angular 6. In the code, there is a div element with *ng-if="edited" as shown below: <div *ngIf="edited"> {{langText}} </div> Initially, when the page loads, edited is set to false and the div is not vis ...

Abbreviating Column Labels in Google Visualization

Is there a way to use the google visualization API to display column headers in an abbreviated form in a table, but show the full labels in a pie chart using the same dataset? Check out this snippet of JavaScript: //create the dashboard and table chart ...