2016-04-06 20 views
6

Tôi có một mảng các đối tượng trong các định dạng sau:ngưng tụ đối tượng mảng đệ quy trong javascript

{ 
    "country": "India", 
    "children": [ 
    { 
     "name": "Karnataka", 
     "type": "State", 
     "children": [ 
     { 
      "name": "", 
      "type": "city" 
     }, 
     { 
      "name": "Bangalore", 
      "type": "city" 
     }, 
     { 
      "name": "Mangalore", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Kerala", 
     "type": "State", 
     "children": [ 
     { 
      "name": "", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Maharashtra", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Mumbai", 
      "type": "city" 
     }, 
     { 
      "name": "Pune", 
      "type": "city" 
     } 
     ] 
    } 
    ] 
} 

Mỗi đối tượng có một yếu tố trẻ em, trong đó có các chi tiết của phần tử. Tôi cần phải đệ quy lặp qua đối tượng json và xóa tất cả các nút có name là chuỗi rỗng cho đến gốc. Đối với định dạng json ở trên, đầu ra phải như sau:

{ 
    "country": "India", 
    "children": [ 
    { 
     "name": "Karnataka", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Bangalore", 
      "type": "city" 
     }, 
     { 
      "name": "Mangalore", 
      "type": "city" 
     } 
     ] 
    }, 
    { 
     "name": "Kerala", 
     "type": "State", 
     "children": [ 
     ] 
    }, 
    { 
     "name": "Maharastra", 
     "type": "State", 
     "children": [ 
     { 
      "name": "Mumbai", 
      "type": "city" 
     }, 
     { 
      "name": "Pune", 
      "type": "city" 
     } 
     ] 
    } 
    ] 
} 

Cách làm điều này trong javascript đệ quy bằng cách sử dụng dấu gạch dưới.

+0

'Array # map' ..? – Rayon

+0

@ RayonDabre — dường như với tôi * reduceRight * và xóa thành viên không mong muốn là tốt hơn, nhưng underscore.js có điều đó không? Nếu không có tích hợp sẵn. – RobG

+0

[Câu hỏi SO này] (http://stackoverflow.com/questions/36171667/find-and-remove-empty-properties-from-objects/36171824) có thể giúp bạn – Aides

Trả lời

3

Đây là một đệ quy giải pháp với Array#filter().

function filterName(a) { 
 
    if (a.name) { 
 
     if (Array.isArray(a.children)) { 
 
      a.children = a.children.filter(filterName); 
 
     } 
 
     return true; 
 
    } 
 
} 
 

 
var object = { "country": "India", "children": [{ "name": "Karnataka", "type": "State", "children": [{ "name": "", "type": "city" }, { "name": "Bangalore", "type": "city" }, { "name": "Mangalore", "type": "city" }] }, { "name": "Kerala", "type": "State", "children": [{ "name": "", "type": "city" }] }, { "name": "Maharashtra", "type": "State", "children": [{ "name": "Mumbai", "type": "city" }, { "name": "Pune", "type": "city" }] }] }; 
 

 
object.children.forEach(filterName); 
 
document.write("<pre>" + JSON.stringify(object, 0, 4) + "</pre>");

1

Hãy thử điều này:

function condense(arr) { 

    arr.children = arr.children.map(function(c) { 
    c.children = c.children.filter(function(c1) { 
     return c1.name; 
    }); 
    return c; 
    }); 

    return arr; 
} 

Tôi lặp qua các trẻ em (với map), sau đó lọc mảng trẻ em với filter. Chỉ những đứa trẻ có tên không rỗng hoặc trống sẽ được giữ lại.

Đây là jsfiddle.

+0

Tôi đã thử phương pháp tương tự. Tôi muốn thử điều này với đệ quy. – zilcuanu

+0

Tại sao? Bạn chỉ có hai mức độ sâu. Hơn nữa, ở cấp độ đầu tiên, bạn giữ trẻ em trống, trên thứ hai bạn xóa chúng. Nó không có vẻ giống như một ứng viên đệ quy tốt. – Derlin

1

Không au fait với underscore.js. Bạn có thể làm điều này với ES5 reduceRight và xóa các thành viên mà bạn không muốn, nó sẽ hiệu quả hơn các cách tiếp cận khác. Sau đây sử dụng đệ quy (mà không phải là hiệu quả như xử lý nối tiếp nhưng có thể ít code), vì vậy bạn có thể tổ các đối tượng sâu như bạn thích:

function removeEmpty(obj) { 
 
    obj.children.reduceRight(function (acc, child, i) { 
 
    if (!child.name) { 
 
     obj.children.splice(i, 1); 
 
    } else if (child.children) { 
 
     removeEmpty(child); 
 
    } 
 
    return null; 
 
    }, null); 
 
    return obj; 
 
} 
 

 
// Test 
 
var data = { 
 
    "country": "India", 
 
    "children": [ 
 
    { 
 
     "name": "Karnataka", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Bangalore", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Mangalore", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Kerala", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    }, 
 
    { 
 
     "name": "Maharashtra", 
 
     "type": "State", 
 
     "children": [ 
 
     { 
 
      "name": "Mumbai", 
 
      "type": "city" 
 
     }, 
 
     { 
 
      "name": "Pune", 
 
      "type": "city" 
 
     } 
 
     ] 
 
    } 
 
    ] 
 
} 
 

 

 
document.write('Original:<br>' + JSON.stringify(data) + '<br><br>' + 
 
       'Modified:<br>' + JSON.stringify(removeEmpty(data)));

+0

Ồ, việc sử dụng 'reduceRight' rất khó hiểu ở đây, vì bạn không làm giảm bất cứ điều gì ... – Bergi

+0

Vâng, nó chỉ là để lặp lại từ chiều dài đến 0, bộ tích lũy được bỏ qua. Có lẽ nên có một * forEachRight *? ;-) Suy nghĩ về nó ngay bây giờ, * trả về null * có thể được bỏ qua. – RobG

+0

Cũng có thể '_' thay vì' acc' – Bergi

1

này là rất cụ thể với ví dụ của bạn.

Link to fiddle

var obj = { 
 
    "country": "India", 
 
    "children": [{ 
 
    "name": "Karnataka", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Bangalore", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Mangalore", 
 
     "type": "city" 
 
    }] 
 
    }, { 
 
    "name": "Kerala", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "", 
 
     "type": "city" 
 
    }] 
 
    }, { 
 
    "name": "Maharashtra", 
 
    "type": "State", 
 
    "children": [{ 
 
     "name": "Mumbai", 
 
     "type": "city" 
 
    }, { 
 
     "name": "Pune", 
 
     "type": "city" 
 
    }] 
 
    }] 
 
}; 
 

 
//Before 
 
document.write("BEFORE: "+JSON.stringify(obj)); 
 
//After 
 
document.write("AFTER: "+JSON.stringify(checkJSON(obj))); 
 

 
function checkJSON(obj) { 
 
    $.each(obj.children, function(index, value) { 
 
    if ($.isArray(value.children)) { 
 
     $.each(value.children, function(index, value) { 
 
     if (value.name == '') { 
 
      delete value.name; 
 
     } 
 
     }); 
 
    } 
 
    }); 
 
    return obj; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

1

Có lẽ không phải là con đường ngắn nhất, nhưng nó hoạt động:

obj.children = _.each(obj.children, filter); 

function filter(child, index, arr) { 
    if (child && child.name === '') { 
    // remove the ones without name 
    arr.splice(index, 1); 

    } else if (_.has(child, 'children')) { 
    // remove nested children 
    child.children = _.each(child.children, filter); 

    // check for empty children array and remove it (if needed) 
    /* 
    if (child.children.length === 0) { 
     delete child['children']; 
    } 
    */ 
    } 

    return child; 
} 

Fiddle: https://jsfiddle.net/gnmosu5p/2/

1

Tôi biết một một đệ quy pproach được yêu cầu nhưng tôi không thể giúp bản thân mình từ cho một lớp lót duy nhất ở đây.

var newData = JSON.parse(JSON.stringify(data).replace(/{"name":"".+?},?/g, "")); 

trong đó data là đối tượng ban đầu được sắp xếp lại.

Hơi chậm so với chức năng mảng nhưng một ưu điểm của phương pháp này là giữ nguyên đối tượng dữ liệu ban đầu vì trong khi tất cả các phương thức mảng sẽ ghi đè đối tượng dữ liệu gốc trừ khi bạn sao chép nó.

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