如何根据 id 查找嵌套数组元素的索引?

Posted

技术标签:

【中文标题】如何根据 id 查找嵌套数组元素的索引?【英文标题】:How to find indexes of nested array elements based on id? 【发布时间】:2021-01-11 15:01:38 【问题描述】:

所以我有一个嵌套的对象数组,其结构如下:

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 ,
      ],
    ,
  ],
];

现在我想创建一个方法,该方法可以基于作为参数给出的id 返回元素的索引,并返回外部元素的索引。例如:

findIdx(pages, 30) 将返回元素 (2) 的 idx 以及外部数组 (0) 的 idx。

findIdx(pages, 110) 将返回元素 (3) 的 idx 以及外部数组 (1) 的 idx。

我能想到的最好的方法是:

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,
  ;

但这需要我指定 columnIdx 作为参数(0 的 columnIdx 将始终等于 pages 数组中的 leftCol,而 1 的 columnIdx 将等于 rightCol )。出于某种原因,我无法让它正常工作。任何帮助将不胜感激。

【问题讨论】:

为什么不获取三个索引,因为三个嵌套数组? 【参考方案1】:

您可以采用动态方法获取所需对象的所有索引。

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]

【讨论】:

【参考方案2】:

reducer 提供了一个相当简洁易读的解决方案,尽管在下面的示例中,它要求结构保持静态,因为它专门引用了 leftColrightCol。您可以通过将解构替换为 Object.entries() 循环来使其更通用。

直接解构页面对象

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));

使用 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));

【讨论】:

谢谢。我已经尝试了所有方法,你的方法似乎效果最好。不敢相信我有多么挣扎嘿嘿。干杯:)。【参考方案3】:

试试:

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);

【讨论】:

【参考方案4】:

你来了。

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);

【讨论】:

以上是关于如何根据 id 查找嵌套数组元素的索引?的主要内容,如果未能解决你的问题,请参考以下文章

根据给出的元素查找此元素在数组中第一次出现的索引

在 JSON 数组中查找元素的索引

FLASH AS3 二维数组如何查找某个元素的索引?

数据结构:使用面向对象模拟数组

如何使用numpy查找数组中元素的索引? [复制]

如何在 int 数组中查找元素的索引?