te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Return object with subset of its attributes - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Return object with subset of its attributes - Stack Overflow

programmeradmin3浏览0评论

I've got a flat JavaScript object like this:

{ 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
  ...
  a lot more attributes
}

I'd like to create a new object which only has a subset of the attributes of the original object.

Something like

var newObject = oldObject.fields(['id', 'username']);

newObject would be

{ 
  id: 3726492,
  username: 'Nicholas'
}

Is there already something like this?

I've got a flat JavaScript object like this:

{ 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
  ...
  a lot more attributes
}

I'd like to create a new object which only has a subset of the attributes of the original object.

Something like

var newObject = oldObject.fields(['id', 'username']);

newObject would be

{ 
  id: 3726492,
  username: 'Nicholas'
}

Is there already something like this?

Share Improve this question asked Nov 12, 2015 at 10:37 HedgeHedge 16.8k45 gold badges154 silver badges260 bronze badges 1
  • 1 I don't think it exists in vanilla, no. As for helper libraries, there's sure to be at least one doing that. – Bartek Banachewicz Commented Nov 12, 2015 at 10:41
Add a ment  | 

5 Answers 5

Reset to default 8

Try this

function pick(data, keys) {
  var result = {};
  
  keys.forEach(function (key) {
    if (data.hasOwnProperty(key)) {
      result[key] = data[key];
    }
  });
  
  return result;
}

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas'
}

var newData = pick(data, ['id', 'kind']);
console.log(newData);

In underscorejs or lodash there is method .pick

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
};

var newObject = _.pick(data, 'id', 'username');
console.log(newObject);
<script src="https://cdnjs.cloudflare./ajax/libs/underscore.js/1.8.3/underscore.js"></script>

You can use Array.prototype.reduce to reduce one object to another using the list of properties:

function subset(obj, propList) {
  return propList.reduce(function(newObj, prop) {
    obj.hasOwnProperty(prop) && (newObj[prop] = obj[prop]);
    return newObj;
  }, {});
}

var obj = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas'
};

var newObj = subset(obj, ['id', 'username']);
console.log(newObj);
document.getElementById('json').innerText = JSON.stringify(newObj);
<pre id="json"></pre>

Not built-in, but you can sure define a simple function that does the job:

var original = {a:1112, b:434, c:666, d:222};

function fieldSubset(obj, fields) {
  var subsetClone = {};
  for( var i=0,l=fields.length; i<l; i++) {
    // This can prevent filling undefined as properties
    if(obj.hasOwnProperty(fields[i])) {
      subsetClone[fields[i]] = obj[fields[i]];
    }
  }
  return subsetClone;
}

fieldSubset(original, ["a", "c"]);

You can also use this in Object.prototype, but be aware that this might happen to conflict with native API in the future versions of JavaScript:

var original = {a:1112, b:434, c:666, d:222};
Object.defineProperty(Object.prototype, "fieldSubset", { 
  value: function(fields) {
      var subsetClone = {};
      for( var i=0,l=fields.length; i<l; i++) {
        // This can prevent filling undefined as properties
        if(this.hasOwnProperty(fields[i])) {
          subsetClone[fields[i]] = this[fields[i]];
        }
      }
      return subsetClone;
    },
  enumerable: false,
  configurable: true}
);  
original.fieldSubset(["a", "c"]);

One liner using Array.prototype.reduce. We are also using Object.assign. The idea is to keep extending a blank object with the keys found in the filters array. If you see, the reduce function takes a callback function with arg1,arg2,arg3 params as the first argument and an empty object as the second argument. This object will be cloned and extended with the help of the keys specified in the filters array.

var a = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
};

var filters = ["id","username","permalink"];

var sub = Object.keys(a).reduce((arg1,arg2,arg3)=>{  var res = {}; if(filters.indexOf(arg2)>=0){  res[arg2] = a[arg2]; } return Object.assign(arg1,res);},{})

console.log(sub);

You haven't specifically mentioned what is the type of values behind your object's keys. Your current answers cover the shallow copy and deep copy. Another alternative would be to create a view of the original object. This would be helpful if you have very large data objects and you do not want them copy in the memory.

function View(obj, properties) {
  var view = {};
  properties.forEach(function(prop) {
    Object.defineProperty(view, prop, {
      get: function() {
             return obj[prop];
           },
      set: function(val) {
             obj[prop] = val;
           },
      enumerable: true,
      configurable: true
    });
  });
  return view;
}

then with your data you can do:

var data = { 
  id: 3726492,
  kind: 'user',
  permalink: 'nicholas',
  username: 'Nicholas',
},
view = new View(data, ['id', 'username']);
view.id; // 3736492
view.username; // Nicholas

of course you have to be aware that you can change your original object just by view.id = 'something else'. However it is easily preventable.

发布评论

评论列表(0)

  1. 暂无评论