Discover the position within a two-dimensional array

Suppose I have an array that contains objects, and each object has its own id property. In this case, I can find the index by writing:

data.findIndex(x=>x.id === newData.id);

Now, if data is an array of arrays of objects, how can I efficiently get two indexes for this data structure? Meaning that data.findIndex would return both i and j conveniently.

Answer №1

To check for specific values in an array, you can utilize Array.includes within the findIndex method.

var data = [
  [1,2,3],
  [4,5,6],
  [7,8,9]
]
var searchParam = 8;
var index = data.findIndex(x=>x.includes(searchParam))
console.log(index)

If dealing with arrays of nested objects, recursion comes in handy to search through them.

var data = [
  [{id: 1},{id: 2},{id: 3}],
  [{id: 4},{id: 5},{id: 6}],
  [{id: 7},{id: 8},{id: 9}]
]
var searchValue = 8;
var index = data.findIndex(x=>{
  return searchInObject(x, searchValue);
})

function searchInObject(obj, searchValue){
  var _s = JSON.stringify(obj);
  if(_s.indexOf(searchValue)>-1){
     if(Array.isArray(obj)){
       return obj.some(function(o){
         if(searchInObject(o, searchValue)) return true;
       });
     }
    else if(typeof(obj) === 'object'){
      for(var k in obj){
        if(searchInObject(obj[k], searchValue)) return true;
      }
    }
    else{
      if(obj === searchValue) return true;
    }
  }
}
console.log(index)

Answer №2

Here is a unique approach to creating a recursive find index function using Array.prototype.reduce() that can navigate through multiple levels of nesting:

const recursiveFindIndex = (data, id) =>
  data.reduce((indexes, item, index) => {
    let subIndex;

    Array.isArray(item) && (subIndex = recursiveFindIndex(item, id));

    if (subIndex && subIndex.length) {
      return indexes.concat([index], subIndex);
    }

    item.id === id && (indexes.push(index));

    return indexes;
  }, []);

const data = [
  { id: 0 },
  [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
  [{ id: 6 }, { id: 7 }, { id: 8 }, { id: 9 }, [
    { id: 10 }, { id: 11 }, { id: 12 }, { id: 13 }, { id: 14 }]
  ]
];

console.log('id: 3', recursiveFindIndex(data, 0));
console.log('id: 3', recursiveFindIndex(data, 3));
console.log('id: 6', recursiveFindIndex(data, 8));
console.log('id: 12', recursiveFindIndex(data, 12));
console.log('id: 3', recursiveFindIndex(data, 20));

Additionally, a more efficient version is presented here which terminates the search once a match is found by utilizing a for loop:

const recursiveFindIndex = (arr, predicate) => {
  let subIndex;
  
  for(let i = 0; i < arr.length; i++) {
    if(Array.isArray(arr[i])) {
      subIndex = recursiveFindIndex(arr[i], predicate);
      
      if(subIndex !== -1) {
        return [i].concat(subIndex);
      }
    } else if(predicate(arr[i])) {
      return [i];
    }
  }

  return -1;
};

const data = [
  { id: 0 },
  [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
  [{ id: 6 }, { id: 7 }, { id: 8 }, { id: 9 }, [
    { id: 10 }, { id: 11 }, { id: 12 }, { id: 13 }, { id: 14 }]
  ]
];

console.log('id: 0', recursiveFindIndex(data, (item) => item.id === 0));
console.log('id: 3', recursiveFindIndex(data, (item) => item.id === 3));
console.log('id: 6', recursiveFindIndex(data, (item) => item.id === 8));
console.log('id: 12', recursiveFindIndex(data, (item) => item.id === 12));
console.log('id: 20', recursiveFindIndex(data, (item) => item.id === 20));

Answer №3

Is this the kind of approach you had in mind?

While it may not be the most sleek solution, it does get the job done:

const updatedData = { id: 2 };
const dataSet = [[{id: 5}, {id: 2}], [{id: 7}, {id: 8}]];

dataSet.reduce((result, array, index) => {
  let position = array.findIndex(item => item.id === updatedData.id);

  if (~position) {
    return [index, position];
  }

  return result;
}, [-1, -1]);

Answer №4

Here is an example utilizing the reduce method:

const items = [
    [{ id: 1 }, { id: 4 }],
    [{ id: 2}, { id: 3 }]
]

const searchId = (items, id) => 
  items.reduce((prev, curr, index) => {
    let result = curr.findIndex(x => x.id === id);
    if(result > -1){
        prev = { index, result }
    }
    return prev;
  }, { index: -1, result: -1 });

Check out this demo on JSFiddle

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

Guide to displaying API data in HTML format

This university assignment involves working on a homework project where I need to utilize a public API in HTML. So far, I have successfully called the public API to display a list of radio channels in the left menu (without adding any click functionality). ...

Managing multiple carousels simultaneously using the middle mouse button in Swiper.js

I am currently utilizing 5 carousels on my screen, all of which are operated by the same navigation buttons. In addition to this, I require the ability to control them using the middle mouse scroll. However, when I activate the mouse wheel control, only ...

Alert: A notification appears when executing Karma on grunt stating that 'The API interface has been updated'

While executing karma from a grunt task, I encountered the following warning: Running "karma:unit" (karma) task Warning: The api interface has changed. Please use server = new Server(config, [done]) server.start() instead. Use --force to continue. A ...

Stop the child component from activating the parent's onClick event

Trying to implement Material-ui within a React project, I am facing an issue with the <IconButton> component and its onClick behavior conflicting with the parent component's behavior. Specifically, I want the <IconButton> to add an item to ...

Splitting a string in Typescript based on regex group that identifies digits from the end

Looking to separate a string in a specific format - text = "a bunch of words 22 minutes ago some additional text". Only interested in the portion before the digits, like "a bunch of words". The string may contain 'minute', & ...

Removing characters from a string with regular expressions

I need to eliminate instances of << any words #_ from the given text. stringVal = "<<Start words#_ I <<love#_ kind <<man>>, <<john#_ <<kind man>> is really <<great>> <<end words#_ "; The d ...

Retrieve the outer-HTML of an element when it is clicked

I am working on a project to develop a tool for locating xpath, and I am seeking the most efficient and user-friendly method for allowing the user to select the desired element on a webpage. Ideally, this selection should be made with just a single click, ...

Refresh Chart Information using Ng2-Charts in Charts.js

Utilizing chart.js and ng2-charts, I am developing gauge charts for my platform to monitor the fluid levels inside a machine's tank. The values are retrieved from an external API, but I am encountering an issue where the charts are rendered before I ...

How can methods access variables from the Vuex store during function calls?

Within my Vue.js component, there is a v-select element. Upon user selection in this widget, the toDo function is triggered from the methods block. However, when attempting to access the value of the filters getter within this function, it consistently ret ...

"Interactive table feature allowing for scrolling, with anchored headers and columns, as well as the option to fix

I'm in need of a table that has certain requirements, as shown in the image. https://i.stack.imgur.com/Z6DMx.png The specific criteria include: The header row (initially blurred) should remain fixed when scrolling down the table The first column s ...

Changing state property upon clicking child element in React is not feasible

I am interested in changing the text color upon clicking it using a function triggered in a child element that affects the parent's state. This is because a specific property of the parent determines whether the text should be one color or another. W ...

execute the execCommand function following an ajax request

I am currently developing a WYSIWYG editor and encountering an issue with image handling using execCommand. Here is a simplified example of my page structure: <div id="buttons_panel"><input id="img_submit" type="button"/></div> <div ...

The trio of Angular, jQuery, and Chrome extensions is a powerful

I'm currently working on developing a Chrome extension that can alter the content of a specific website. However, since I don't have access to the source code of the website, I need to make these modifications using JavaScript. The goal is to ma ...

JSON function invocation is failing to load

This is my JavaScript script, When I call the function calculate(), the JSON method ConvertDataTabletoString() only gets called once, when I load the page. I want the method to be called every 5 seconds. I am calling a VB.NET function in .aspx. How can ...

Is it possible to use Koajs without needing to include the --harmony tag?

Following the merge of iojs into Node, I assumed that I could run koajs without the need for the --harmony tag (as it would have support for generators from es6). Inside my server.js file, I have the following code: var koa = require('koa'); va ...

Node.js process.exec() function allows you to asynchronously spawn a subprocess

After writing the code, I ran it and found that the terminal was unresponsive with no output, causing the program to be stuck. var util=require('util') var exec=require('child_process').exec; exec('iostat 5',function(err,stdo ...

Is there a way to retrieve the headers from an HTTP response in JavaScript that wasn't initiated by an AJAX request?

I have a login page setup to send an HTTP post request to the server, which then redirects me to another page on the server in the response message. On this new page, I need to access the location header to obtain a specific value for future server tasks. ...

Tips for showing/hiding textboxes based on select options:

I am currently working on a project that allows users to enter their personal information. I need help figuring out how to show or hide textboxes based on the selection made in a dropdown menu. The dropdown menu in question is for marital status. The opt ...

Can an HTML DIV be resized along with its contents?

Is it possible to scale a container with animated elements inside to fit the browser window, or do you have to adjust each child element individually? ...

Using Angular as a template engine: A simple guide

My goal is to utilize Angular as a template engine and then pass the resulting HTML code to another library. In my template file named template.html: <div><h1><span data-ng-show="details.rs">{{details.rs}}</span></h1></di ...