Searching for the positions of nested array elements using their identifiers

Looking for some assistance with a nested array of objects structured like this:

let pages = [
  [
    {
      leftCol: [
        { height: 34, id: 10 },
        { height: 18, id: 20 },
        { height: 45, id: 30 },
        { height: 59, id: 40 },
      ],
    },
    {
      rightCol: [
        { height: 34, id: 50 },
        { height: 34, id: 60 },
        { height: 34, id: 70 },
      ],
    },
  ],
  [
    {
      leftCol: [
        { height: 34, id: 80 },
        { height: 18, id: 90 },
        { height: 45, id: 100 },
        { height: 59, id: 110 },
      ],
    },
    {
      rightCol: [
        { height: 34, id: 120 },
        { height: 34, id: 130 },
        { height: 34, id: 140 },
      ],
    },
  ],
];

We need to create a method that can find the index of an element based on its id as well as find the index of the outer array. For instance:

findIdx(pages, 30) should return the index of the element (2) and the index of the outer array (0).

findIdx(pages, 110) should return the index of the element (3) and the index of the outer array (1).

The current method looks like this:

function getIdxAndPageNumOfColumn(array, columnIdx, payloadId) {
  let idx;
  let pageNum;

  for (pageNum = 0; pageNum < array.length; pageNum++) {
    let leftCol = array[pageNum][0].leftCol;
    let rightCol = array[pageNum][1].rightCol;
    let column = columnIdx === 0 ? leftCol : rightCol;
    idx = column.findIndex(item => item.id == payloadId);
    if (idx > -1) break;
  }

  return {
    idx: idx,
    pageNum: pageNum,
  };
}

However, this method requires specifying a columnIdx parameter which seems to be causing issues. Any suggestions on how to improve this would be greatly appreciated.

Answer №1

To efficiently retrieve all the indexes of the desired object, consider implementing a dynamic approach.

function searchIndices(array, id) {
    function search(arr) {
        if (!arr) return;
        let inner,
            index = arr.findIndex(obj => {
                if (obj.id === id) return true;
                if (Array.isArray(obj)) return inner = search(obj);
                return inner = search(obj.leftCol || obj.rightCol);
            });
        return index !== -1 && [index, ...(inner || [])];
    }

    return search(array);
}

let pages = [[{ leftCol: [{ height: 34, id: 10 }, { height: 18, id: 20 }, { height: 45, id: 30 }, { height: 59, id: 40 }] }, { rightCol: [{ height: 34, id: 50 }, { height: 34, id: 60 }, { height: 34, id: 70 }] }], [{ leftCol: [{ height: 34, id: 80 }, { height: 18, id: 90 }, { height: 45, id: 100 },{ height: 59, id: 110 }] }, { rightCol: [{ height: 34, id: 120 }, { height: 34, id: 130 }, { height: 34, id: 140 }] }]];

console.log(searchIndices(pages, 30));  // [0, 0, 2]
console.log(searchIndices(pages, 110)); // [1, 0, 3]

Answer №2

Utilizing a reducer in your code can lead to more concise and readable solutions. However, the current implementation requires a static structure with specific references to leftCol and rightCol. To make it more versatile, consider replacing destructuring with an Object.entries() loop.

Directly accessing data from the page object

let pages = [/* Array of page objects with leftCol and rightCol arrays */];

function getIdxAndPageNumOfColumn(array, payloadId) {

  const pageAndIndex = array.reduce((acc, [{leftCol}, {rightCol}], i) => {
    if ((leftMatch = leftCol.findIndex(p => p.id === payloadId)) !== -1) {
      acc['idx'] = leftMatch;
      acc['pageNum'] = i;
      acc['colIdx'] = 0;
    } else if ((rightMatch = rightCol.findIndex(p => p.id === payloadId)) !== -1) {
      acc['idx'] = rightMatch;
      acc['pageNum'] = i;
      acc['colIdx'] = 1;
    }
    return acc
  }, {})
  
  return pageAndIndex;
}

console.log(getIdxAndPageNumOfColumn(pages, 30));
console.log(getIdxAndPageNumOfColumn(pages, 110));


Alternative approach using Object.values

let pages = [/* Array of page objects with leftCol and rightCol arrays */];

function getIdxAndPageNumOfColumn(array, payloadId) {

  const pageAndIndex = array.reduce((acc, pArr, pi) => {
    pArr.forEach((col, ci) => {
      Object.values(col).forEach(v => {
        if ((match = v.findIndex(p => p.id === payloadId)) !== -1) {
          acc['idx'] = match;
          acc['pageNum'] = pi;
          acc['colIdx'] = ci;
        }
      });
    });
    return acc
  }, {});
  
  return pageAndIndex;
}

console.log(getIdxAndPageNumOfColumn(pages, 30));
console.log(getIdxAndPageNumOfColumn(pages, 110));

Answer №3

Give this a shot:

const searchPage = (pages, id) =>
  new Promise((resolve) => {
    pages.map((page) => {
      page.map((p) => {
        Object.entries(p).map(([key, value]) => {
          const result = value.filter((item) => item.id === id);
          if (result.length > 0) {
            resolve(result[0]);
          }
        });
      });
    });
  });

searchPage(pagesArray, desiredIdToFind).then(console.log);

Answer №4

Here is the code snippet you requested.

function locateIndex(elements, identifier) {
    for (let pointer = 0; pointer < elements.length; pointer++) {
        const rows = elements[pointer];
        for (const column of rows) {
            for (const key in column) {
                const itemFound = column[key].find((obj) => obj.id == identifier);
                if (itemFound) return pointer;
            }
        }
    }
}

const result = locateIndex(elementsArray, 110);
console.log(result);

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

Leverage the Axios package to make requests within a for loop

I'm new to JavaScript and currently working on a project using Vue.js, Axios, and the API available at . The goal of this project is to retrieve NBA player statistics for a homework assignment. I could use some assistance in addressing certain issues. ...

Encountering a CORS error while trying to fetch a YouTube page in React

Can someone help me extract the HTML markup of a YouTube video page? Below is the code I have so far: async function get_subtitles(video_id: string): Promise<string> { if (video_id.includes('https://') || video_id.includes('http:// ...

How to deactivate the mobile hardware back button functionality in Ionic 2

Our team has been developing a business application and we've encountered a perplexing issue. Every time we press the mobile hardware back button, our application's GUI becomes disrupted. Despite dedicating numerous hours to finding a solution, t ...

Sending a post request in AngularJS using the $resource API

As a beginner in angularjs, I am working on creating a login form that connects to a REST API URL when the user submits the form. http://XXX/XXX/index.php/report/login/format/json Using PostMan REST client to configure the URL works fine! However, when ...

Doing a simple HTTP GET request with RxJS does not do anything

I'm encountering an issue with my code: export class Test { constructor(private http: Http) {} logResponse(): Observable<any> { return this.http.get('http://google.com') .do(data => console.log("All: " + JSON.stringify(dat ...

The String.match() function may not always return the expected result, as it can sometimes return null

I have been attempting to utilize a regex to find a specific match within a file, however, the match function consistently returns null even when the match is clearly present in the data. When I tested the same data and regex on RegExr, it successfully id ...

Three.js: transforming textures into data textures

Currently, my goal is to create a delayed webcam viewer using javascript, utilizing Three.js for its WebGL capabilities. At the moment, I am able to capture frames from the webcam and display them after a specified time interval using canvas and getImageD ...

Tips for invoking a function from a JavaScript file within an Angular component

This particular query remains unanswered and pertains to AngularJS. I am seeking a solution specifically for Angular, as none of the existing answers online seem to be effective in my case. Here is an outline of my code: Columns.js export class Columns { ...

Display or conceal elements by utilizing ng-show/ng-hide according to specific conditions

Here is the code snippet I am working with: <input class="form-field form-control" type="text" name="Website" ng-model="vm.infodata.Website" placeholder="Website Address" maxlength="50" required ng-pattern="/^(www\.)?[a-zA-Z0-9_&bs ...

Ways to verify the uniqueness of usernames within Firebase

I have been working on a function to check if a username is unique in my Firebase database. Despite researching and implementing code, it doesn't seem to work as expected. Any assistance would be greatly appreciated - what am I missing? onChangeUser ...

Volar and vue-tsc are producing conflicting TypeScript error messages

During the development of my project using Vite, Vue 3, and TypeScript, I have set up vue-tsc to run in watch mode. I am utilizing VS Code along with Volar. This setup has been helpful as it displays all TypeScript errors in the console as expected, but I ...

Steer clear of changing props directly in VueJS to prevent unintended

I am working with a component that has props, and I need to change the value from false to true. However, I encountered a message in the Chrome console advising against mutating a prop directly because it will be overwritten whenever the parent component r ...

Inspecting boxes and merged text result

Seeking assistance with coding for a combined text box output. View this image to see the final result A. Input: Users must select from various checkbox options. B. Output: The chosen text strings should be collectively displayed in an updated text box ...

A game inspired by Cube Crash, using Actionscript 3.0

I'm attempting to develop a game similar to the one found at using actionscript 3 (flash builder). I have successfully created an array of bricks that are visible when the game starts, but I am unsure how to identify a group of bricks within the arra ...

Prevent selection of weekend dates in Angular Bootstrap datepicker with a personalized directive

I have integrated the Angular Bootstrap datepicker plugin into my Angular application. To customize the date pickers in my app, I created a custom directive. In certain places, I need to disable weekends in the date picker. I have added the functions to d ...

Is it necessary to reload the document ready event after injecting an Ajax response into the DOM?

My form includes a color picker, which is set up in the Document Ready section along with the select input tags. However, I need to retrieve data through AJAX on another page and have that response replace the form. When I do this, the jquery colorpicker s ...

The collapsing html menu remains in place instead of navigating to the designated id

After clicking on a link, my jQuery code moves the "a" element to the specified id in the href attribute of the link. Below is an HTML code snippet: <nav class="navbar w-100 align-items-center navbar-expand-md fixed-top bg-white border-bottom shadow-s ...

The problem of interpreting JSON using the JavaScript eval() function

Here is the JSON string provided : { "name":"Ruby on Rails Baseball Jersey", "price":"19.99", "id":"1025786064", "image":"" }, { "name":"Ruby on Rails Baseball Jersey", "price":"19.99", "id":"1025786064", "image":"" }, { "name ...

Error: IndexOutOfRangeException occurred within my array

My code uses recursion to find the minimum number in an array. However, when I run the program, I encounter an ArrayIndexOutOfBoundsException error at line 36 (Assignment9.java) where it compares values using if (previousMin > numbers[endIndex]) and als ...

Experiencing problems with the response from the Netlify Lambda function.. consistently receiving undefined results

I've been working on setting up a lambda function to handle authentication, validation, and sending of a contact form. As I'm new to lambda functions, my code might have some flaws. However, despite my efforts, I am struggling to modify the resp ...