Reputation: 3272
So I have a nested array of objects that has the following structure:
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 },
],
},
],
];
Now I would like to create a method that can return the index of an element based on a id
given as a parameter aswell as return the index of the outer element. For example:
findIdx(pages, 30)
would return the idx of the element (2) aswell as the idx of the outer array (0).
findIdx(pages, 110)
would return the idx of the element (3) aswell as the idx of the outer array (1).
The best I could come up with is the following method:
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,
};
}
But this requires me to specify a columnIdx
as a parameter (a columnIdx
of 0 will always be equal to the leftCol
in the pages array, and columnIdx
of 1 would be equal to rightCol
). For some reason I can't get this to work properly. Any help would be appreciated.
Upvotes: 0
Views: 3993
Reputation: 386728
You could take a dynamic approach for getting all indices of the wanted object.
function findIdx(array, id) {
function find(array) {
if (!array) return;
let inner,
index = array.findIndex(o => {
if (o.id === id) return true;
if (Array.isArray(o)) return inner = find(o);
return inner = find(o.leftCol || o.rightCol);
});
return index !== -1 && [index, ...(inner || [])];
}
return find(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(findIdx(pages, 30)); // [0, 0, 2]
console.log(findIdx(pages, 110)); // [1, 0, 3]
Upvotes: 2
Reputation: 12918
A reducer makes for a fairly concise and readable solution, though in the example below it requires the structure to remain static as it references leftCol
and rightCol
specifically. You could make it more general by replacing the desctructuring with an Object.entries()
loop.
Directly destructuring the page object
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 }, ], }, ],];
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));
Using Object.values
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 },], },],];
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));
Upvotes: 1
Reputation: 980
Here you are.
function findIdx(pages, id) {
for (let index = 0; index < pages.length; index++) {
const cols = pages[index];
for (const e of cols) {
for (const key in e) {
const item = e[key].find((a) => a.id == id);
if (item) return index;
}
}
}
}
const item = findIdx(pages, 110);
console.log(item);
Upvotes: 1
Reputation: 323
Try:
const findPage = (pages, pageid) =>
new Promise((res) => {
pages.map((page) => {
page.map((p) => {
Object.entries(p).map(([k, v]) => {
const x = v.filter((_) => _.id === pageid);
if (x.length > 0) {
res(x["0"]);
}
});
});
});
});
findPage(pages, idWhichYouSearch).then(console.log);
Upvotes: 1