2016-02-01 9 views
10

Mam tablice obiektów głęboko zagnieżdżonych. Chciałbym napisać funkcję wyodrębniania dowolnych obiektów podrzędnych z tych tablic. W niektórych przypadkach wartości zagnieżdżonych właściwości to wartości i obiekty, w innych przypadkach są to tablice.Wyodrębniaj głęboko zagnieżdżone obiekty podrzędne za pomocą nazwy właściwości z domieszką

Przykłady tablic są poniżej:

[{parent: {level1: {level2: 'data'}}}] 

[{parent: {level1: [{level2: {...}}, {level2: {...}}, {level2: {...}}]}}] 

[{parent: {level1: [{level2: {level3: 'data'}}, {level2: {..}}, {level2: {..}}]}}] 

Wywołanie funkcji ekstrakcji na takiej tablicy powinna spowodować tablicę obiektów, które są zainteresowani

Przykładowe wywołanie funkcji i jej wyników. dla przykładu tablic powyżej:

extractChildren(source, 'level2') = [{level2: 'data'}] 

extractChildren(source, 'level2') = [{level2: {...}, level2: {...}, level2: {...}] 

extractChildren(source, 'level3') = [{level3: 'data'}] 

Czy istnieje zwięzły sposób, aby osiągnąć ten cel z lodash czy powinienem użyć regularne JavaScript iterować przez właściwości?

P.S. Potraktujcie to jako ekwiwalent XPath select all nodes with the name "nodename"

+2

Ty powinien al więc wyjaśnij przykład, jakie obiekty potomne powinny zostać wyodrębnione, szczególnie w odniesieniu do tego, jak powinien wyglądać wynik, jeśli jeden potencjalny cel zawiera inny potencjalny cel. – Tomalak

+1

Pokaż więcej, proszę. Czy możesz podać oczekiwany sygnał wejściowy, "wywołanie" i oczekiwany wynik? –

+0

dodano więcej informacji – krl

Odpowiedz

1

Mam nadzieję, że to pomaga:

'use strict'; 

let _ = require("lodash"); 
let source = [{parent: {level1: [{level2: {level3: 'data'}}, {level2: {}}, {level2: {}}]}}]; 

function extractChildren(source, specKey) { 
    let results = []; 
    let search = function(source, specKey) { 
     _.forEach(source, function(item) { 
      if (!!item[specKey]) { 
       let obj = {}; 
       obj[specKey] = item[specKey]; 
       results.push(obj); 
       return; 
      } 

      search(item, specKey); 
     }); 
    }; 

    search(source, specKey); 
    return results; 
}; 

console.log(extractChildren(source, 'level3')); 
// [ { level3: 'data' } ] 
+0

Kończy się z 'Maksymalnym przekroczeniem maksymalnego limitu połączeń wywołania' z domyślną konfiguracją Node.js i moje rzeczywiste dane – krl

+0

Jak duże są twoje dane? – Festo

+0

Do 10 poziomów głębokości lub tak, ale niezbyt duże (dziesiątki KB), ponieważ w przeciwnym razie użyłbym strumieni.) Nieważne. Nadal muszę podejść do problemu inaczej, ponieważ muszę zbierać niektóre dane z obiektów nadrzędnych również i taka prosta funkcja 'extractChildren' nie będzie działać w takim przypadku.) – krl

1

Od this question:

Elegant:

function find_obj_by_name(obj, key) { 
    if(!(obj instanceof Array)) return []; 

    if (key in obj) 
     return [obj[key]]; 

    return _.flatten(_.map(obj, function(v) { 
     return typeof v == "object" ? find_obj_by_name(v, key) : []; 
    }), true); 
} 

Wydajny:

function find_obj_by_name(obj, key) { 
    if(!(obj instanceof Array)) return []; 

    if (key in obj) 
     return [obj[key]]; 

    var res = []; 
    _.forEach(obj, function(v) { 
     if (typeof v == "object" && (v = find_obj_by_name(v, key)).length) 
      res.push.apply(res, v); 
    }); 
    return res; 
} 
+0

" Wydajność "można poprawić, używając wanilowego' forEach' zamiast '_.forEach' – vsync

+0

. t zrozumieć co to jest 'fn (v, key)'. czy to przetestowałeś? co to jest 'fn'? – vsync

+0

Teraz widzę, że skopiowałeś jej [odpowiedź] (http://stackoverflow.com/a/15643385/104380), zmienił go i nie zweryfikował wyniku. – vsync