Нужен доступ к элементу на основе последовательного свойства объекта или свойств из массива объекта, у меня есть значение для поиска

#javascript #reactjs

#javascript #reactjs

Вопрос:

 const levels = [
    {
      indexId: 'A',
      level: 1,
      name: 'A',
      parent: '0',
    },
    {
      indexId: 'A-A1',
      level: 2,
      name: 'A1',
      parent: 'A',
    },
    {
      indexId: 'A-A1-A11',
      level: 3,
      name: 'A11',
      parent: 'A-A1',
    },
    {
      indexId: 'A-A1-A11-A111',
      level: 4,
      name: 'A111',
      parent: 'A-A1-A11',
    },
    {
      indexId: 'A-A1-A11-A112',
      level: 4,
      name: 'A112',
      parent: 'A-A1-A11',
    },
    {
      indexId: 'A-A1-A12',
      level: 3,
      name: 'A12',
      parent: 'A-A1',
    },
    {
      indexId: 'A-A1-A12-A121',
      level: 4,
      name: 'A121',
      parent: 'A-A1-A12',
    },
    {
      indexId: 'A-A1-A12-A121-A1211',
      level: 5,
      name: 'A1211',
      parent: 'A-A1-A12-A121',
    },
    {
      indexId: 'A-A2',
      level: 2,
      name: 'A2',
      parent: 'A',
    },
    {
      indexId: 'A-A2-A21',
      level: 3,
      name: 'A21',
      parent: 'A-A2',
    },

    {
      indexId: 'A-A2-A22',
      level: 3,
      name: 'A22',
      parent: 'A-A2',
    },
    {
      indexId: 'A-A3',
      level: 2,
      name: 'A3',
      parent: 'A',
    },
    {
      indexId: 'A-A3-A31',
      level: 3,
      name: 'A31',
      parent: 'A-A3',
    },
    {
      indexId: 'A-A3-A32',
      level: 3,
      name: 'A32',
      parent: 'A-A3',
    },
  ]

 
  const maxLevel = levels.filter(
    l => l.level === Math.max(...levels.map(l => l.level))
  )

  const arrayStrings = []

  function stackLetter(l) {
    for (let index = 1; index <= l.length; index  ) {
      arrayStrings.push(l.slice(0, index))
    }
  }

stackLetter(maxLevel[0].indexId.split('-'))
  console.log(arrayStrings)

const buildTree = arrayStrings
    .map(arr => arr.join('-'))
    .map(s => {
      return levels.filter(l => l.indexId === s)
    })

  console.log(buildTree)
  

Изначально я получил самую длинную ветвь с максимальным уровнем

 output array = [["A"],["A-A1"],["A-A1-A12"],["A-A1-A12-A121"],["A-A1-A12-A121-A1211"]]
  

если я выбираю indexId = ‘A-A1-A12’>, я получаю [[«A»], [«A-A1»], [«A-A1-A12»] ]

но ожидаемый результат — это код, который может быть любой ветвью, связанной с выбранным мной узлом, это может быть =

[[«A»],[«A-A1»], [«A-A1-A12»], [«A-A1-A12-A121»], [«A-A1-A12-A121-A1211»]]

или, если я выберу ‘A-A3’, это должно дать

[[«A»],[«A-A3»],[«A-A3-A31»]]

или

[[«A»],[«A-A3»],[«A-A3-A32»]]

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

1. Вы уже пробовали что-то самостоятельно относительно выбора?

2. Пожалуйста, укажите больше ожидаемого результата. Для 'A-A3' выбора вы хотите [["A"],["A-A3"],["A-A3-A31"]] or [["A"],["A-A3"],["A-A3-A32"]] . Что означает или ? Один из них, не имеет значения, какой? Первое? Оба?

3. поскольку A3 имеет два дочерних элемента A31 и A32, поэтому or означает, что он может предоставить любой из них, да, я пробовал, но я пробовал использовать функцию stackLetter, если я выбираю узел с индексом id = A-A31, я получаю [[«A»], [«A-A3»]] не его дочерние узлы, сравнение идентификатора индекса с индексом обхода узлов или с родительским идентификатором даст мне еще 1 дочерний узел, но более глубокие узлы, как я упоминал выше.

Ответ №1:

Следующий код выводит то, что требуется в OP. Это reduce исходный массив, «запоминающий» до сих пор «самый глубокий» id и level . Если для обработанного item level не является непрерывным или indexId не соответствует selection или «запоминается» id , он не добавляется в выходной массив.

Возвращаемая ветвь является «первой по глубине», то есть первой, которую она находит, не обязательно самой глубокой.

 const levels = [
    {
      indexId: 'A',
      level: 1,
      name: 'A',
      parent: '0',
    },
    {
      indexId: 'A-A1',
      level: 2,
      name: 'A1',
      parent: 'A',
    },
    {
      indexId: 'A-A1-A11',
      level: 3,
      name: 'A11',
      parent: 'A-A1',
    },
    {
      indexId: 'A-A1-A11-A111',
      level: 4,
      name: 'A111',
      parent: 'A-A1-A11',
    },
    {
      indexId: 'A-A1-A11-A112',
      level: 4,
      name: 'A112',
      parent: 'A-A1-A11',
    },
    {
      indexId: 'A-A1-A12',
      level: 3,
      name: 'A12',
      parent: 'A-A1',
    },
    {
      indexId: 'A-A1-A12-A121',
      level: 4,
      name: 'A121',
      parent: 'A-A1-A12',
    },
    {
      indexId: 'A-A1-A12-A121-A1211',
      level: 5,
      name: 'A1211',
      parent: 'A-A1-A12-A121',
    },
    {
      indexId: 'A-A2',
      level: 2,
      name: 'A2',
      parent: 'A',
    },
    {
      indexId: 'A-A2-A21',
      level: 3,
      name: 'A21',
      parent: 'A-A2',
    },

    {
      indexId: 'A-A2-A22',
      level: 3,
      name: 'A22',
      parent: 'A-A2',
    },
    {
      indexId: 'A-A3',
      level: 2,
      name: 'A3',
      parent: 'A',
    },
    {
      indexId: 'A-A3-A31',
      level: 3,
      name: 'A31',
      parent: 'A-A3',
    },
    {
      indexId: 'A-A3-A32',
      level: 3,
      name: 'A32',
      parent: 'A-A3',
    },
]

// auxiliary function to compare if 1st string starts with the second one or vice versa (according to legth)
function stringMatch(s1,s2) {
   return s1.length > s2.length ? s1.startsWith(s2) : s2.startsWith(s1);
}

// main function
function extract(input,selection="") {
   var id = "", level = 0; // initial conditions, storing "last" added item data
   return input.reduce((answer,item) => { // loop the input array and reduce it ...
      // do nothing (return unchenged answer) if ... 
      if (item.level !== level   1) return answer; // ... level is not plus one from current level
      if (!item.indexId.startsWith(id)) return answer; // ... indexId does not start with current id
      if (!stringMatch(item.indexId,selection)) return answer; // ... item.indexId does not fit selection
      // update "last" data
      level = item.level;
      id = item.indexId;
      // return updated answer
      return [...answer,id];
   },[]); // reduction starts from empty array
}

// test
console.log(extract(levels));
// [ 'A', 'A-A1', 'A-A1-A11', 'A-A1-A11-A111' ]
console.log(extract(levels,"A-A2"));
// [ 'A', 'A-A2', 'A-A2-A21' ]
console.log(extract(levels,"A-A3"));
// [ 'A', 'A-A3', 'A-A3-A31' ]