2016-09-16 38 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

相关问题