Javascript получает полный индекс вложенного объекта

#javascript

#javascript

Вопрос:

 const items = [
   { id: 'item1',
     children: [ 
      { id: 'item1-1',
        children: [
          { id: 'item1-1-1' },
          { id: 'item1-1-2' },
          { id: 'item1-1-3'
            children: [
               { id: 'item1-1-3-1'}
            ]
          },
        ]
      },
      { id: 'item1-2',
        children: [
          { id: 'item1-2-1' }
        ]
      }
    ]
   },
   { id: 'item2' }
]
  

То, что я хочу, похоже на приведенное ниже,

 function getFullDepthOfObject(){
  ...
}

getFullIndexOfObject('item1') =====> return '1'
getFullIndexOfObject('item1-2') =====> return '1-2'
getFullIndexOfObject('item1-1-1') =====> return '1-1-1'
getFullIndexOfObject('item1-1-2') =====> return '1-1-2'
getFullIndexOfObject('item2') ===> return '2'
  

Я боролся с этим слишком много времени, но у меня ничего не получилось. Я думаю, что я должен сложить каждый из parent индексов, но я не знаю, как получить его родительский. Есть ли способ сделать это?

Не разбирает id строку. Каждый идентификатор содержит случайную строку. Идентификатор like item1-2 предназначен для упрощения демонстрации.

Я думаю, что мой способ слишком подробный… Я пытался, как…

 // Get Full Index of item1-1


// First, get the target's depth.
var depth = 0;

function getDepthOfId(object, id) {
    var level;
    if (object.id === id) return 1;
    object.children amp;amp; object.children.some(o => level = getDepthOfId(o, id));
    return level amp;amp; level   1;
}

depth = getDepthOfId(items[0], 'item1-1');
console.log('depth === ', depth)


// Then, iterate recursively with length of depth.

var indexStacks = [];


function getNestedIndexOfId(obj, id, index) {
    if (obj.id === id) {
        indexStacks = [index, ...indexStacks]
        return index;
    }

    if (obj.children) {
        depth  ;
        obj.children.map((child, i) => {
            getNestedIndexOfId(child, id, i)
        })
    }
}

// I can get the inner index, but I can't get its parent id.
// I don't know how to this..

function getParentId(obj, id){
    // ...?
    var parentId;
    return parentId;
}

for(var i=0; i<depth; i  ){
        getNestedIndexOfId('...')
}


// full path will be 
indexStacks.join('-')
  

Комментарии:

1. Разве этого недостаточно? getFullIndexOfObject = index =>index.replace('item', ''); Похоже, что это тот результат, который вы ищете

2. @MiroslavGlamuzina Идентификатор элемента указан для удобства понимания, мой код имеет идентификатор с uuid

3. Как выглядит реальный код? Потому что, даже если это так, но оно все еще находится в формате item__UUID__ , это все равно будет действительным.

Ответ №1:

 const items = [
  { id: 'item1',
    children: [
      { id: 'item1-1',
        children: [
          { id: 'item1-1-1' },
          { id: 'item1-1-2' },
          { id: 'item1-1-3',
            children: [
              { id: 'item1-1-3-1'}
            ]
          }
        ]
      },
      { id: 'item1-2',
        children: [
          { id: 'item1-2-1' }
        ]
      }
    ]
  },
  { id: 'item2' }
];

const searchIt = (node, search, path = '', position = 0) => {
  if (node.id amp;amp; node.id === search) {return path !== '' ? `${path}-${position}` : position;}
  if (!node.children) {return false}
  const index = node.children.findIndex((x) => x.id amp;amp; x.id === search);
  if (index >= 0) {
    return path !== '' ? `${path}-${index   1}` : index   1;
  }
  for (let i = 0; i < node.children.length; i  ) {
    const result = searchIt(node.children[i], search, path !== '' ? `${path}-${i 1}` : i   1, i);
    if (result){
      return resu<
    }
  }
  return false;
};

console.log(searchIt({children: items}, 'item1-1'));
console.log(searchIt({children: items}, 'item1-1-1'));
console.log(searchIt({children: items}, 'item1-1-2'));
console.log(searchIt({children: items}, 'item1-1-3'));
console.log(searchIt({children: items}, 'item1-1-3-1'));
console.log(searchIt({children: items}, 'item1-2-1'));
console.log(searchIt({children: items}, 'item1-1-3-2'));
console.log(searchIt({children: items}, 'item1-2-2'));
console.log(searchIt({children: items}, 'item3'));
  

Ответ №2:

Вы могли бы использовать рекурсивный и итеративный подход. При обнаружении возвращается путь от самого внутреннего объекта к внешнему вызову функции.

 function getPath(array, id) {
    var resu<
    array.some((o, i) => {
        var temp;
        if (o.id === id) return result = `${i   1}`;
        if (temp = getPath(o.children || [], id)) return result = `${i   1}-${temp}`;
    });
    return resu<
}

const items = [{ id: 'item1', children: [{ id: 'item1-1', children: [{ id: 'item1-1-1' }, { id: 'item1-1-2' }, { id: 'item1-1-3', children: [{ id: 'item1-1-3-1'}] }] }, { id: 'item1-2', children: [{ id: 'item1-2-1' }] }] }, { id: 'item2' }];


console.log(getPath(items, 'item1'));     // '1'
console.log(getPath(items, 'item1-2'));   // '1-2'
console.log(getPath(items, 'item1-1-1')); // '1-1-1'
console.log(getPath(items, 'item1-1-2')); // '1-1-2'
console.log(getPath(items, 'item2'));     // '2'  

Ответ №3:

Вы можете решить эту проблему с помощью рекурсии. Я отредактировал свой блок кода и превратил его в тестируемый фрагмент. Мне пришлось исправить ошибку в ваших данных (пропущенная запятая или что-то еще, не помню).

 const items = [
   { id: 'itemA',
     children: [ 
      { id: 'item1-1',
        children: [
          { id: 'item1-1-1' },
          { id: 'item1-1-2' },
          { id: 'item1-1-3', children: [ { id: 'item1-1-3-1'} ] },
        ]
      },
      { id: 'item1-2', children: [ { id: 'item1-2-1' } ] },
    ],
   },
   { id: 'item2' }
];


const getItemLevel = (targetKey, item, depth = 0) => {
   if (item.id === targetKey) return depth;
   let foundLevel = null;
   if (item.children) {
     item.children.forEach((child) => {
       if (foundLevel) return;
       foundLevel = getItemLevel(targetKey, child, depth  1);
     })
   }
   return foundLevel;
}

console.log(getItemLevel('item1-1-1', { id:'root', children: items }));
console.log(getItemLevel('item2', { id:'root', children: items }));
console.log(getItemLevel('item1-1-3-1', { id:'root', children: items }));
console.log(getItemLevel('keydoesnotexist', { id:'root', children: items }));  

Комментарии:

1. Я думаю, что это возвращает только глубину элемента, а не полный путь. Пожалуйста, прочтите мой вопрос еще раз… Спасибо.

2. Он уже использует рекурсию, но ему нужно увидеть отношения родитель / потомок / внук.

3. хорошо, тогда я явно не понимаю вопроса, потому что я читаю и перечитываю его, и я все еще не понимаю. Может быть, потому, что его идентификаторы сбивают с толку? Какой результат вы хотите?

4. Например, если у вас был элемент с идентификатором «A», который был дочерним элементом «B», который был дочерним элементом «C», вы хотите, чтобы результат был «C-B-A»?

5. @JSager индексирует эти элементы. Каждый элемент находится внутри массива. Итак, если элемент item1-1-1 будет печатать 1-1-1 от корня к объекту, каждый индекс его дедушкиного индекса соответствует его индексу. Хотя на самом деле это не фактический индекс, index 1 на самом деле.

Ответ №4:

простой способ:

 const recursiveFind = (arr, id, res = {indexes: [], found: false}) => {
  if (!Array.isArray(arr)) return res

  const index = arr.findIndex(e => e.id === id)

  if (index < 0) {
    for (let i = 0; i < arr.length; i  ) {
      res.indexes.push(i 1)
      const childIndexes = recursiveFind(arr[i].children, id, res)
      if (childIndexes.found){
        return childIndexes
      }
    }
  }
  else {
    res.found = true
    res.indexes.push(index 1)
  }

  return res
}

recursiveFind(items, 'item1-1-2').indexes.join('-')
  

Ответ №5:

Если можно использовать Lodash Deepdash, то:

 let path;

_.eachDeep(items,(val,key,parent,context)=>{
  if(path) return false;
  if(val.id=='item1-1-2'){
    path=context.path;
    return false;
  }
},{tree:true,pathFormat:'array'});

console.log(_(path).without('children').map(v=>parseInt(v) 1).join('-'));
  

Вот codepen для этого