2016-09-16 36 views
1

正如標題所說,我試圖在找到之後安全地獲取對象的屬性。下劃線 - 在_.find之後安全地獲取屬性

假設,我有這樣的數組:

var ppl = [ 
    { id: 1, name: 'Smith' }, 
    { id: 2, name: 'Wesson' }, 
    { id: 3, name: 'Remington' }, 
    { id: 4, name: 'Colt' } 
]; 

所以我試圖讓通過ID這恭敬君子之一的名字,所以我用_.find

var person = _.find(ppl, function(p) { return p.id === 2; }); 

我正在尋找一種方法來在_鏈安全得到name。喜歡的東西:

var personName = _.chain(ppl) 
        .find(function(p) { return p.id === 2; }) 
        .get('name') //<-- can't find appropriate method :(
        .values(); 

OFC我可以用支票不喜歡它,如果(人& & person.name)...甚至寫我自己的原型方法,但不希望推倒重來。

回答

1

我相信GruffBunny是在正確的你似乎可以用Lodash,而不是下劃線。我也覺得在答案中提供的解決方案非常優雅,但我想展示一個替代方案。

注:我會提供一個下劃線的答案,因爲這個問題被標記爲這樣也是一種Lodash之一,因爲OP似乎是有意在

Underscore.js

有一件事,我一直髮現有點尷尬是你的確切情況 - 鏈(一個數組) - >做操作 - >找到 - >做其他事情。 Underscore中的對象函數稍微偏離。但是,我們仍然可以嘗試做到這一點:

var ppl = [ 
 
    { id: 1, name: 'Smith' }, 
 
    { id: 2, name: 'Wesson' }, 
 
    { id: 3, name: 'Remington' }, 
 
    { id: 4, name: 'Colt' } 
 
]; 
 

 
function findName(id) { 
 
    return _.chain(ppl) 
 
    .findWhere({id: id}) // <- shorter syntax than _.find and does the same as supplying your own function. 
 
         // It's even shorter than the already short fat arrow syntax which would be: (p => p.id === 2) 
 
    .pick('name') // <- extract a new object that has a single property "name" 
 
    .map() //<- 1. for objects, it's equivalent to mapping the values only, e.g., _.map(_.values(obj)) 
 
     //^- 2. if no argument is specified, it defaults to _.identity 
 
    .first() // <- since the previous step returns an array of one value this step unwraps it and leaves you with a plain value 
 
    .value(); // end chain, return result 
 
} 
 

 
console.log("Find ID = 2:", findName(2)); 
 
console.log("Find ID = 42:", findName(42)); 
 
console.log('Find ID = "2" (string value):', findName("2"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

所以,這將做的工作,但它是一個有點尷尬。你缺少.get,所以你必須採取 - >地圖 - >首先做等效。這並不是嚴重的壞,但它並不盡如人意。一種替代方法是將您的單個結果保存在一個數組中,這將允許您運行其他功能。所以,你可以做到這一點

_.chain(ppl) 
    .where({id: id}) //it's basically "filterWhere" like _.findWhere but it returns all results in an array. In this case, it would be a single result purely so we can do the below 
    .map('name') //<- allows you to map by name of the property but only with arrays 
    .first() // <- still have to unwrap 
    .value(); 

讓我們來看看相當於

Lodash

Lodash好一點,因爲它有幾分流暢的語法,也有一個好一點的處理對象,所以你不會面臨需要將它們保持在一個數值範圍內的情況。

var ppl = [ 
 
    { id: 1, name: 'Smith' }, 
 
    { id: 2, name: 'Wesson' }, 
 
    { id: 3, name: 'Remington' }, 
 
    { id: 4, name: 'Colt' } 
 
]; 
 

 
function findName(id, defaultName) { 
 
    return _.chain(ppl) 
 
    .find({id: id}) //<- Lodash does not have _.findWhere but the normal _.find already handles this 
 
    .get('name') // <- see, much simpler! You can also supply a second argument which would be returned as a default value 
 
    .value(); 
 
} 
 

 
console.log("Find ID = 2:", findName(2)); 
 
console.log("Find ID = 42:", findName(42)); 
 
console.log('Find ID = "2" (string value):', findName("2"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

+0

太棒了!謝謝。我使用帶有角度UI路由器的下劃線,所以試圖使用它來最大限度地發揮潛力。 – Kindzoku

+0

我很高興能幫上忙。我將離開Lodash解決方案,以顯示這些方法之間的差異。 – vlaz

2

正如你使用get我假設你使用lodash而不是下劃線。如果是這樣,那麼你可以使用defaultTo這是在4.14.0版本介紹:

var ppl = [ 
 
    { id: 1, name: 'Smith' }, 
 
    { id: 2, name: 'Wesson' }, 
 
    { id: 3, name: 'Remington' }, 
 
    { id: 4, name: 'Colt' } 
 
]; 
 

 
var nullPerson = { 
 
    id: 0, 
 
    name: 'null' 
 
} 
 

 
var personName = _.chain(ppl) 
 
    .find({id: 99}) 
 
    .defaultTo(nullPerson) 
 
    .get('name') 
 
    .value(); 
 

 
console.log(personName);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>

+0

我喜歡這樣。我不知道'defaultTo'。 – vlaz

+0

我正在使用Underscore,正如你在標題中看到的那樣。我剛纔提到,我如何看到解決方案,但下劃線沒有這種方法。 – Kindzoku

相關問題