使用下划线查询对象

时间:2014-10-15 09:13:18

标签: javascript underscore.js

我有一个具有嵌套属性的对象,其中一些有一个'选择'属性。我试图使用下划线获取这些值,即使我成功了代码看起来不是很可读:

_.chain(config)
  .pairs()
  .map(function(e) {
    var s = {};

    s[e[0]] = _.chain(e[1])
      .filter(function(e) {
        if (e.selected) {
          return e;
        }
      })
      .pluck('name')
      .join(',')
      .value();

    return s;
  })
  .flatten()
  .filter(function(e) {
    if (_.values(e)[0] !== '') {
      return e;
    }
  })
  .reduce(_.extend)
  .value();

这是我使用的配置对象:

var config = {
 'property__1': [
   {name: 'test1', selected: 1},
   {name: 'test2'}
 ],
 'property__2': [
   {name: '0'},
   {name: '1', selected: 1},
   {name: '2'},
   {name: '3'},
   {name: '4', selected: 1}
 ],
 'property__3': [
   {name: '0'},
   {name: '1'},
   {name: '2', selected: 1},
   {name: '3'}
 ],
 'property__4': [
   {name: 'test1'},
   {name: 'test2', selected: 1}
 ]
};

并希望获得以下输出:

{
  "property__1": "test1",
  "property__2": "1,4",
  "property__3": "2",
  "property__4": "test2"
}

还有什么我可以做的重构它,或者我不知道的任何可能有助于使这段代码更具可读性的属性吗?

2 个答案:

答案 0 :(得分:2)

有些观点:

  • filter回调应该返回一个布尔值,而不是应该收集的对象。它只是return e.selected == 1,甚至只是返回1undefined
  • 我不确定
  • 需要.flatten()
  • _.values(e)[0]看起来特别糟糕。您应该考虑在制作对象之前过滤

我和

一起去
_.reduce(config, function(s, e, k) {
    var vals = _.filter(e, _.property("selected"));
    if (vals.length)
        s[k] = _.pluck(vals, "name").join();
    return s;
}, {});

不可否认,.length的测试与空.name的字符串检查不同,但我想这是你真正想要的

当然,你可以将其延伸到

_.chain(config)
  .pairs()
  .map(function(p) {
      return [p[0], _.filter(p[1], _.property("selected"))];
  }).filter(function(p) {
      return p[1].length;
  }).map(function(p) {
      return [p[0], _.chain(p[1]).pluck("name").join().value()];
  })
  .object()
  .value();

...这更像是你原来的那个,但只看起来很长而不是更好。

答案 1 :(得分:0)

我是使用jQuery每个循环完成的。代码更简单易读。

var output = {}
//first each loop will iterate over property__1,property__2,...
$.each(config, function(propertyName) {
    //here 'this' will refer to the array that 'property__1' holds, 
    //and the next each loop will iterate over this array.
    $.each(this, function(){ 
        //here 'this' will refer to the element of the array,
        //for example object {name: 'test1', selected: 1}
        if(typeof this.selected !== 'undefined'){ //check if 'selected' property is present
            //if present then map required value on propertyName
            if(output[propertyName]){
                output[propertyName] += ',' + this.name; //append comma seperated if already mapped
            } else {        
                output[propertyName] = this.name; //map directly if for the first time
            }
        }
    });
});
console.log(output);

让我知道这有助于你:)