2013-07-10 103 views
10

我有文件夾的對象/文件看起來像這樣:Underscore.js findWhere嵌套對象

{ 
    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' 
     } 
    } 
    } 
} 

而且它可以去6-7級深生兒育女的文件夾。

我想找到路徑等於我提供的字符串的對象。無論它有多深。

我使用下劃線只做頂層:

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

我該怎麼做了深刻的,嵌套的搜索。下劃線是否有這個或我需要建立一個混合與遞歸?

回答

11

這是不是最漂亮的代碼,但是我測試了它,它似乎工作,你問的方式。它被設置爲lodash /下劃線mixin,但可以使用。用法是這樣的:

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

實現:

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

如果發現值,lodash會返回false,如果下劃線支持該值,則通過代碼查看可能返回{}會導致它突然出現,但我不確定。 – dariusriggins

+0

很好,謝謝! – wesbos

+0

偉大的解決方案,就像一個魅力。我想知道爲什麼這不是默認內置於US/LD的! – dbau

9

而不是findWhere,使用filter,它採用函數作爲謂詞而不是鍵值映射。使用遞歸函數來檢查當前節點和可能的子節點。事情是這樣的:

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); 

編輯

假設這個工作,你可能想使一個功能getRecursiveFilter(searchText)。以下是如何將看:在這裏,recursiveFilter使用arguments.callee to call itself recursively

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

注意。


Here's a working demo.

+0

是否有可能沒有'subl-child.html'硬編碼? – wesbos

+0

@確定,只需將它添加爲'searchText'旁邊的另一個參數,我猜?看到這裏:http://jsfiddle.net/Fy9Ej/1/ – McGarnagle

+0

對不起,我想找到路徑===字符串的對象。無論其最高級別還是100級別。這裏沒有兩個字符串。 – wesbos