2013-07-10 48 views
10

Tôi có một đối tượng của thư mục/tập tin mà trông như thế này:Underscore.js findWhere đối tượng lồng nhau

{ 
    about.html : { 
    path : './about.html' 
    }, 
    about2.html : { 
    path : './about2.html' 
    }, 
    about3.html : { 
    path : './about3.html' 
    }, 
    folderName : { 
    path : './folderName', 
    children : { 
     sub-child.html : { 
     path : 'folderName/sub-child.html' 
     } 
    } 
    } 
} 

Và nó có thể đi 6-7 cấp độ sâu của các thư mục có con.

Tôi muốn tìm đối tượng nơi đường dẫn bằng một chuỗi mà tôi cung cấp. Bất kể nó sâu đến đâu.

Tôi đang sử dụng gạch mà chỉ thực hiện cấp cao nhất:

_.findWhere(files,{path:'./about2.html'} 

Làm thế nào tôi có thể làm một sâu, tìm kiếm lồng nhau. Có gạch dưới có một cái gì đó cho điều này hoặc tôi cần phải xây dựng một mixin với đệ quy?

Trả lời

11

Đây không phải là mã đẹp, nhưng tôi đã thử nghiệm nó ra và nó dường như làm việc theo cách bạn đang yêu cầu. Nó được thiết lập như một mixin lodash/underscore, nhưng có thể được sử dụng tuy nhiên. Cách sử dụng sẽ là như thế này:

_.findDeep(testItem, { 'path': 'folderName/sub-child.html' }) 

Thực hiện:

findDeep: function(items, attrs) { 

    function match(value) { 
    for (var key in attrs) { 
     if(!_.isUndefined(value)) { 
     if (attrs[key] !== value[key]) { 
      return false; 
     } 
     } 
    } 

    return true; 
    } 

    function traverse(value) { 
    var result; 

    _.forEach(value, function (val) { 
     if (match(val)) { 
     result = val; 
     return false; 
     } 

     if (_.isObject(val) || _.isArray(val)) { 
     result = traverse(val); 
     } 

     if (result) { 
     return false; 
     } 
    }); 

    return result; 
    } 

    return traverse(items); 

} 
+0

Trả về false có lodash để thoát ra khỏi vòng lặp nếu tìm thấy giá trị, không chắc chắn nếu gạch dưới hỗ trợ, xem qua mã, có lẽ trở lại {} sẽ khiến nó bị vỡ, nhưng tôi không chắc chắn. – dariusriggins

+0

Hoạt động tuyệt vời, cảm ơn một tấn! – wesbos

+0

Giải pháp tuyệt vời, hoạt động như một sự quyến rũ. Tôi tự hỏi tại sao điều này không được xây dựng vào US/LD theo mặc định! – dbau

9

Thay vì findWhere, sử dụng filter, có chức năng làm vị từ thay vì bản đồ khóa-giá trị. Sử dụng hàm đệ quy để kiểm tra nút hiện tại và các con có thể. Một cái gì đó như thế này:

var searchText = './about2.html'; 

var recursiveFilter = function(x) { 
    return x.path == searchText || 
     (typeof x.children != 'undefined' && recursiveFilter(x.children['sub-child.html'])); 
}; 

_.filter(files, recursiveFilter); 

Sửa

Giả sử công trình này, có thể bạn sẽ muốn thực hiện một chức năng getRecursiveFilter(searchText). Dưới đây là rằng sẽ trông như thế nào:

function getRecursiveFilter(searchText) { 
    var recursiveFilter = function(x) { 
     return x.path == searchText || 
      (typeof x.children != 'undefined' 
       && arguments.callee(x.children['sub-child.html'])); 
    }; 
    return recursiveFilter; 
} 

Lưu ý rằng ở đây, recursiveFilter sử dụng arguments.callee to call itself recursively.


Here's a working demo.

+0

Có thể có nó mà không cần mã hóa 'subl-child.html' không? – wesbos

+0

@ Chắc chắn, chỉ cần thêm nó làm thông số khác bên cạnh 'searchText', tôi đoán vậy? Xem tại đây: http://jsfiddle.net/Fy9Ej/1/ – McGarnagle

+0

Xin lỗi, tôi muốn tìm đối tượng có đường dẫn === chuỗi. Bất kể cấp cao nhất hay 100 cấp độ sâu. Không có hai dây ở đây. – wesbos

5

này đã có một câu trả lời được chấp nhận, nhưng câu trả lời khác này là rất sạch sẽ và hoàn hảo cho tình huống tương tự của tôi: https://stackoverflow.com/a/21600748/1913975 _.filter + _.where

+0

Đây không phải là đệ quy. – David

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