2016-02-01 30 views
10

Tôi có mảng các đối tượng lồng nhau sâu. Tôi muốn viết một hàm để trích xuất các đối tượng con tùy ý từ các mảng này. Trong một số trường hợp giá trị của thuộc tính lồng nhau là giá trị và đối tượng, trong trường hợp khác chúng là mảng.Trích xuất các đối tượng con lồng nhau sâu sắc theo tên thuộc tính với lodash

Ví dụ về mảng dưới:

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

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

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

Gọi chức năng khai thác trên một mảng như vậy nên kết quả trong một mảng của các đối tượng mà chúng ta đang quan tâm đến

Ví dụ về gọi hàm và kết quả của nó. cho các mảng ví dụ trên:

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

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

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

Có cách nào ngắn gọn để đạt được điều này với lodash hoặc tôi nên sử dụng JavaScript thông thường để lặp qua các thuộc tính?

P.S. Nghĩ về nó như tương đương với XPath select all nodes with the name "nodename"

+2

Bạn nên al do đó giải thích với một ví dụ về những đối tượng con nào cần được trích xuất, chính xác, đặc biệt là về kết quả trông như thế nào nếu một mục tiêu tiềm năng chứa một mục tiêu tiềm năng khác. – Tomalak

+1

Hiển thị thêm, vui lòng. Bạn có thể cung cấp đầu vào được mong đợi, "cuộc gọi" và đầu ra dự kiến ​​không? –

+0

thêm thông tin – krl

Trả lời

1

Tôi hy vọng, nó giúp:

'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

Kết thúc bằng 'Kích thước ngăn xếp cuộc gọi tối đa vượt quá 'với cấu hình Node.js mặc định và Dữ liệu thực tế của tôi – krl

+0

Dữ liệu của bạn lớn đến mức nào? – Festo

+0

Tối đa 10 cấp độ hoặc hơn, nhưng không quá lớn (hàng chục KB), vì nếu không tôi sẽ sử dụng luồng. Không cần phải làm gì. thu thập một số dữ liệu từ các đối tượng cha mẹ và chức năng 'extractChildren' đơn giản như vậy sẽ không hoạt động cho trường hợp đó. – krl

1

Từ 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); 
} 

hiệu quả:

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

Hiệu quả" "có thể được cải thiện bằng cách sử dụng vanilla' forEach' thay vì '_.forEach' – vsync

+0

Ngoài ra, tôi không ' t hiểu này là gì fn (v, key) '. bạn đã kiểm tra này? là gì' fn'? – vsync

+0

Tôi bây giờ thấy bạn đã sao chép anot [answer] (http://stackoverflow.com/a/15643385/104380) của cô ấy, đã thay đổi nó và không xác minh kết quả. – vsync

Các vấn đề liên quan