Поиск элемента в массиве объектов JS

Имеется объект data. Необходимо получить "name", зная "key". К примеру, если key = '1.002', нужно получить name = 'Это имя нужно получить'. Уровень вложенности неограничен.

const data = [
    {
        key: '1.001',
        data: {
            id: '1.001',
            name: 'qwe',
        },
        children: [
            {
                key: '1.002',
                data: {
                    id: '1.002',
                    name: 'Это имя нужно получить',
                },
                children: null,
            },
            {
                key: '1.003',
                data: {
                    id: '1.003',
                    name: 'qwe',
                },
                children: null,
            },
            {
                key: '1.004',
                data: {
                    id: '1.004',
                    name: 'qwe',
                },
                children: [
                    {
                        key: '1.005',
                        data: {
                            id: '1.005',
                            name: 'qwe',
                        },
                        children: null,
                    },
                    {
                        key: '1.006',
                        data: {
                            id: '1.006',
                            name: 'qwe',
                        },
                        children: null,
                    },
                ]
            }
        ]
    },
    {
        key: '2.001',
        data: {
            id: '2.001',
            name: 'qwe',
        },
        children: [
            {
                key: '2.002',
                data: {
                    id: '2.002',
                    name: 'qwe',
                },
                children: null,
            },
            {
                key: '2.003',
                data: {
                    id: '2.003',
                    name: 'qwe',
                },
                children: null,
            },
        ]
    }
]

Ответы (5 шт):

Автор решения: Grundy

Чтобы найти какой-то элемент, достаточно просто обойти все элементы.

Для этого можно поместить все доступные узлы в массив.

Брать из этого массива по одному узлу и проверять, подходит он под условие или нет. Если подходит, то поиск закончен - достаточно вернуть данный узел и взять нужное поле.

Если не подходит и есть дочерние узлы - нужно добавить их в массив доступных узлов.

Если добавлять в начало - будет обход в глубину, если добавлять в конец - обход в ширину.

Пример:

const data = [{
    key: '1.001',
    data: {
      id: '1.001',
      name: 'qwe',
    },
    children: [{
        key: '1.002',
        data: {
          id: '1.002',
          name: 'Это имя нужно получить',
        },
        children: null,
      },
      {
        key: '1.003',
        data: {
          id: '1.003',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '1.004',
        data: {
          id: '1.004',
          name: 'qwe',
        },
        children: [{
            key: '1.005',
            data: {
              id: '1.005',
              name: 'qwe',
            },
            children: null,
          },
          {
            key: '1.006',
            data: {
              id: '1.006',
              name: 'qwe',
            },
            children: null,
          },
        ]
      }
    ]
  },
  {
    key: '2.001',
    data: {
      id: '2.001',
      name: 'qwe',
    },
    children: [{
        key: '2.002',
        data: {
          id: '2.002',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '2.003',
        data: {
          id: '2.003',
          name: 'qwe',
        },
        children: null,
      },
    ]
  }
]

function findByKey(arr, key) {
  var nodes = arr.slice();
  while (nodes.length) {
    const node = nodes.shift();

    if (node.key === key) return node;

    if (node.children) {
      nodes.push(...node.children);
    }
  }
}

console.log(findByKey(data, '1.002')?.data?.name);

→ Ссылка
Автор решения: Apollon Seven

const data = [{
    key: '1.001',
    data: {
      id: '1.001',
      name: 'qwe',
    },
    children: [{
        key: '1.002',
        data: {
          id: '1.002',
          name: 'Это имя нужно получить',
        },
        children: null,
      },
      {
        key: '1.003',
        data: {
          id: '1.003',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '1.004',
        data: {
          id: '1.004',
          name: 'qwe',
        },
        children: [{
            key: '1.005',
            data: {
              id: '1.005',
              name: 'qwe',
            },
            children: null,
          },
          {
            key: '1.006',
            data: {
              id: '1.006',
              name: 'qwe',
            },
            children: null,
          },
        ]
      }
    ]
  },
  {
    key: '2.001',
    data: {
      id: '2.001',
      name: 'qwe',
    },
    children: [{
        key: '2.002',
        data: {
          id: '2.002',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '2.003',
        data: {
          id: '2.003',
          name: 'qwe2003',
        },
        children: null,
      },
    ]
  }
]

const getNameByKey = (array, key) => {
  if (array) {
    for (let i = 0; i < array.length; i++) {
      if (array[i].key === key) {
        return array[i].data.name
      } else {
        const childrenByKey = getNameByKey(array[i].children, key)
        if (childrenByKey) return childrenByKey
      }
    }
  }
  return null
}

console.log(getNameByKey(data, "2.003"))

→ Ссылка
Автор решения: Aleksandr Belous

У вас данные имеют древовидную структуру, следовательно, можно использовать алгоритмы для обхода деревьев. Например, обход в глубину. Однако у вас может быть множество корневых элементов, поэтому применим функцию ко всем узлам и вернем преобразованный результат.

const data = [{
    key: '1.001',
    data: {
      id: '1.001',
      name: 'qwe',
    },
    children: [{
        key: '1.002',
        data: {
          id: '1.002',
          name: 'Это имя нужно получить',
        },
        children: null,
      },
      {
        key: '1.003',
        data: {
          id: '1.003',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '1.004',
        data: {
          id: '1.004',
          name: 'qwe',
        },
        children: [{
            key: '1.005',
            data: {
              id: '1.005',
              name: 'qwe',
            },
            children: null,
          },
          {
            key: '1.006',
            data: {
              id: '1.006',
              name: 'qwe',
            },
            children: null,
          },
        ]
      }
    ]
  },
  {
    key: '2.001',
    data: {
      id: '2.001',
      name: 'qwe',
    },
    children: [{
        key: '2.002',
        data: {
          id: '2.002',
          name: 'qwe',
        },
        children: null,
      },
      {
        key: '2.003',
        data: {
          id: '2.003',
          name: 'qwe',
        },
        children: null,
      },
    ]
  }
];

const findName = (tree, key) => {
  if (tree.key === key) {
    return tree.data.name;
  }
  const children = tree.children;
  if (children !== null) {
    return children.flatMap((node) => findName(node, key));
  }
  return [];
};

const result = String(data.flatMap((rootNode) => findName(rootNode, '1.002')));

console.log(result); // Это имя нужно получить
→ Ссылка
Автор решения: Stanislav Volodarskiy

visit посещает все узлы в дереве. Это генератор, лишней памяти и времени он не тратит:

const visit = function*(roots) {
    for (const node of roots) {
        yield node;
        yield* visit(node.children || []);
    }
};

findKey ищет ключ в дереве, посещает все узлы, сверяет ключи, возвращает имя для первого найденного:

const findKey = (data, key) => {
    for (const node of visit(data)) {
        if (node.key === key) {
            return node.data.name;
        }
    }
    return undefined;
};

Использование:

console.log(findKey(data, '1.002'));
console.log(findKey(data, '10.002'));
$ node temp.js
Это имя нужно получить
undefined
→ Ссылка
Автор решения: Max Dupley

Для решения задачи нужно реализовать рекурсивную функцию, которая будет проходить по объекту data и искать совпадение ключа.

Если совпадение найдено, возвращается соответствующее имя.

Вот пример функции:

function findNameByKey(data, targetKey) {
  for (const item of data) {
    if (item.key === targetKey) {
      return item.data.name; // Нашли ключ, возвращаем имя
    }
    if (item.children) {
      const result = findNameByKey(item.children, targetKey); // Рекурсивный вызов
      if (result) {
        return result; // Если найдено в дочерних элементах, возвращаем результат
      }
    }
  }
  return null; // Если ключ не найден
}

// Пример использования
const keyToFind = '1.002';
const name = findNameByKey(data, keyToFind);
console.log(name); // Выведет: "Это имя нужно получить"
→ Ссылка