2011-11-10 47 views
27

Tôi đang cố gắng lặp qua một đối tượng lồng nhau để lấy một đối tượng cụ thể được xác định bằng một chuỗi. Trong đối tượng mẫu bên dưới, chuỗi định danh là thuộc tính "label". Tôi không thể quấn đầu xung quanh làm thế nào để lặp lại thông qua cây để trả lại đối tượng thích hợp. Bất kỳ trợ giúp hoặc đề xuất sẽ được đánh giá cao.Lặp lại thông qua các đối tượng JavaScript lồng nhau

var cars = 
    { 
     label: 'Autos', 
     subs: 
      [ 
       { 
        label: 'SUVs', 
        subs: [] 
       }, 
       { 
        label: 'Trucks', 
        subs: [ 
           { 
           label: '2 Wheel Drive', 
           subs: [] 
           }, 
           { 
           label: '4 Wheel Drive', 
           subs: [ 
              { 
              label: 'Ford',           
              subs: [] 
              }, 
              { 
              label: 'Chevrolet', 
              subs: []          
              } 
             ]       
           } 
          ]  
       }, 
       { 
        label: 'Sedan', 
        subs: [] 
       } 
      ] 
    } 
+1

có thể trùng lặp của [Traverse tất cả các nút của cây đối tượng JSON bằng JavaScript] (http://stackoverflow.com/questions/722668/traverse-all-the-nodes-of-a-json-object-tree- with-javascript) –

+0

Bạn đang muốn tìm kiếm thông qua tất cả các cấp của đối tượng cho một nhãn tùy ý? (Aha, đi ngang, đó là từ tôi đang tìm kiếm.) – Dave

+0

Có thể trùng lặp của [đối tượng truy cập/xử lý (lồng nhau), mảng hoặc JSON] (http://stackoverflow.com/questions/11922383/access-process-nested -objects-arrays-or-json) – Liam

Trả lời

34

Bạn có thể tạo một hàm đệ quy như thế này để làm một sâu -truy cập đầu tiên của đối tượng cars.

var findObjectByLabel = function(obj, label) { 
    if(obj.label === label) { return obj; } 
    for(var i in obj) { 
     if(obj.hasOwnProperty(i)){ 
      var foundLabel = findObjectByLabel(obj[i], label); 
      if(foundLabel) { return foundLabel; } 
     } 
    } 
    return null; 
}; 

mà có thể được gọi như vậy

findObjectByLabel(car, "Chevrolet"); 
+0

Trong bài gốc, các xe con không phải là thuộc tính của đối tượng xe, nhưng được chứa trong một mảng 'subs'. –

+0

@JamesClark Tôi biết. Nó vẫn hoạt động, và nó linh hoạt trong trường hợp anh ta có nhiều hơn một thuộc tính mảng nếu anh ta quyết định thay đổi tên của 'subs' thành cái gì đó khác. –

+1

Đệ quy là xấu đối với các đối tượng rất sâu. Bạn sẽ nhận được tràn ngăn xếp. –

2

Các mã sau đây giả định không có tham chiếu vòng tròn, và giả định subs luôn là một mảng (và không phải null trong nút lá):

function find(haystack, needle) { 
    if (haystack.label === needle) return haystack; 
    for (var i = 0; i < haystack.subs.length; i ++) { 
    var result = find(haystack.subs[i], needle); 
    if (result) return result; 
    } 
    return null; 
} 
2

Để tăng hiệu suất cho các thao tác cây nữa là tốt để chuyển đổi cây vào xem bộ sưu tập dòng, như [obj1, obj2, obj3]. Bạn có thể lưu trữ các quan hệ đối tượng cha-con để dễ dàng điều hướng đến phạm vi cha/con.

Tìm kiếm phần tử bên trong bộ sưu tập hiệu quả hơn sau đó tìm phần tử bên trong cây (đệ quy, tạo chức năng bổ sung động, đóng).

0

sửa đổi từ Peter Olson 's câu trả lời: https://stackoverflow.com/a/8085118

  1. có thể tránh được giá trị chuỗi !obj || (typeof obj === 'string'
  2. có thể tùy chỉnh của bạn chính

var findObjectByKeyVal= function (obj, key, val) { 
    if (!obj || (typeof obj === 'string')) { 
    return null 
    } 
    if (obj[key] === val) { 
    return obj 
    } 

    for (var i in obj) { 
    if (obj.hasOwnProperty(i)) { 
     var found = findObjectByKeyVal(obj[i], key, val) 
     if (found) { 
     return found 
     } 
    } 
    } 
    return null 
} 
0

Đây là một dead- phương pháp đơn giản chỉ sử dụng 3 biến wit hout đệ quy.

function forEachNested(O, f){ 
    O = Object.values(O); 
    var cur; 
    while (O.length){ 
     cur = O.pop() 
     f(cur); 
     if (typeof cur === 'object' && cur.constructor === Object) 
      O.push.apply(O, Object.values(cur)); 
    } 
} 

Nếu bạn gặp rắc rối với sự tham khảo tròn (giá trị ví dụ có đối tượng của một là đối tượng A chính nó trong như rằng đối tượng A chứa chính nó), hoặc bạn chỉ cần các phím sau đó là giải pháp chậm hơn sau đã có sẵn.

function forEachNested(O, f){ 
    O = Object.entries(O); 
    var cur; 
    function applyToEach(x){return cur[1][x[0]] === x[1]} 
    while (O.length){ 
     cur = O.pop(); 
     f(cur[0], cur[1]); 
     if (typeof cur[1] === 'object' && cur[1].constructor === Object && 
      !O.some(applyToEach)) 
      O.push.apply(O, Object.entries(cur[1])); 
    } 
} 

Vì các phương pháp này không sử dụng bất kỳ đệ quy nào, các chức năng này rất phù hợp cho các khu vực nơi bạn có thể có hàng nghìn độ sâu.

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