/ / Jak rekurencyjnie używać Array.prototype.find () podczas zwracania pojedynczego obiektu? - javascript, rekurencja

Jak rekurencyjnie używać Array.prototype.find () podczas zwracania pojedynczego obiektu? - javascript, rekursja

Większy problem, który próbuję rozwiązać, biorąc pod uwagę te dane:

var data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4, children: [
{ id: 6 },
{ id: 7, children: [
{id: 8 },
{id: 9 }
]}
]},
{ id: 5 }
]

Chcę zrobić funkcję findById(data, id) to się zwraca { id: id }. Na przykład, findById(data, 8) powinien powrócić { id: 8 }, i findById(data, 4) powinien powrócić { id: 4, children: [...] }.

W tym celu wykorzystałem Array.prototype.find rekurencyjnie, ale wpadł w kłopoty, gdy return ciągle zaciera obiekty. Moja implementacja zwraca ścieżka do konkretnego obiektu.

Na przykład kiedy użyłem findById(data, 8), zwraca ścieżka do { id: 8 }:

 { id: 4, children: [ { id: 6 }, { id: 7, children: [ { id: 8}, { id: 9] } ] }

Zamiast tego chciałbym, żeby po prostu wrócił

{ id: 8 }

Implementacja (Node.js v4.0.0)

jsfiddle

var data = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4, children: [
{ id: 6 },
{ id: 7, children: [
{id: 8 },
{id: 9 }
]}
]},
{ id: 5 }
]

function findById(arr, id) {
return arr.find(a => {
if (a.children && a.children.length > 0) {
return a.id === id ? true : findById(a.children, id)
} else {
return a.id === id
}
})
return a
}

console.log(findById(data, 8)) // Should return { id: 8 }

// Instead it returns the "path" block: (to reach 8, you go 4->7->8)
//
// { id: 4,
//   children: [ { id: 6 }, { id: 7, children: [ {id: 8}, {id: 9] } ] }

Odpowiedzi:

1 dla odpowiedzi № 1

Po prostu użyłbym zwykłej pętli i rekurencyjnego wyszukiwania stylu:

function findById(data, id) {
for(var i = 0; i < data.length; i++) {
if (data[i].id === id) {
return data[i];
} else if (data[i].children && data[i].children.length && typeof data[i].children === "object") {
findById(data[i].children, id);
}
}
}

//findById(data, 4) => Object {id: 4, children: Array[2]}
//findById(data, 8) => Object {id: 8}

8 dla odpowiedzi № 2

Problem, jaki masz, to bulgotanie znaleziska. Jeśli identyfikator zostanie znaleziony w zagnieżdżonej strukturze, wywołanie zwrotne próbuje zwrócić element, który jest interpretowany jako true, wartość dla znalezienia.

The find Metoda wykonuje funkcję wywołania zwrotnego jeden raz dla każdego elementu obecnego w tablicy, dopóki nie znajdzie takiego, w którym wywołanie zwrotne zwraca prawdziwą wartość. [MDN]

Zamiast znaleźć, sugerowałbym użycie stylu rekurencyjnego do wyszukiwania z krótkim zwarciem, jeśli zostanie znaleziony.

var data = [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4, children: [{ id: 6 }, { id: 7, children: [{ id: 8 }, { id: 9 }] }] }, { id: 5 }];

function findById(data, id) {
function iter(a) {
if (a.id === id) {
result = a;
return true;
}
return Array.isArray(a.children) && a.children.some(iter);
}

var result;
data.some(iter);
return result
}

console.log(findById(data, 8));