Поиск элемента в массиве объектов 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 шт):
Чтобы найти какой-то элемент, достаточно просто обойти все элементы.
Для этого можно поместить все доступные узлы в массив.
Брать из этого массива по одному узлу и проверять, подходит он под условие или нет. Если подходит, то поиск закончен - достаточно вернуть данный узел и взять нужное поле.
Если не подходит и есть дочерние узлы - нужно добавить их в массив доступных узлов.
Если добавлять в начало - будет обход в глубину, если добавлять в конец - обход в ширину.
Пример:
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);
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"))
У вас данные имеют древовидную структуру, следовательно, можно использовать алгоритмы для обхода деревьев. Например, обход в глубину. Однако у вас может быть множество корневых элементов, поэтому применим функцию ко всем узлам и вернем преобразованный результат.
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); // Это имя нужно получить
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
Для решения задачи нужно реализовать рекурсивную функцию, которая будет проходить по объекту 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); // Выведет: "Это имя нужно получить"