648

オブジェクトがあるとします:

elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

プロパティのサブセットを持つ新しいオブジェクトを作成したいと考えています。

 // pseudo code
 subset = elmo.slice('color', 'height')

 //=> { color: 'red', height: 'unknown' }

どうすればこれを達成できますか?

4

32 に答える 32

995

オブジェクトの分解とプロパティの短縮形の使用

const object = { a: 5, b: 6, c: 7  };
const picked = (({ a, c }) => ({ a, c }))(object);

console.log(picked); // { a: 5, c: 7 }


Philipp Kewisch より:

これは実際には、即座に呼び出される無名関数です。これらはすべて、MDN のDestructuring Assignmentページにあります。拡張フォームはこちら

let unwrap = ({a, c}) => ({a, c});

let unwrap2 = function({a, c}) { return { a, c }; };

let picked = unwrap({ a: 5, b: 6, c: 7 });

let picked2 = unwrap2({a: 5, b: 6, c: 7})

console.log(picked)
console.log(picked2)

于 2016-09-05T15:12:31.693 に答える
216

Lodashをご覧になることをお勧めします。多くの優れたユーティリティ機能があります。

たとえば、pick()まさにあなたが求めるものです:

var subset = _.pick(elmo, ['color', 'height']);

フィドル

于 2013-07-22T06:58:48.703 に答える
110

もう少し冗長ですが、 Array.prototype.reduce を使用することで、2 年前に他の誰もがアンダースコア/ロダッシュを推奨していたことを実現できます

var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});

このアプローチは、反対側から解決します。オブジェクトを取得してプロパティ名を渡して抽出するのではなく、プロパティ名の配列を取得して、それらを新しいオブジェクトに減らします。

最も単純なケースではより冗長ですが、ここでのコールバックは非常に便利です。たとえば、新しいオブジェクトの 'color' プロパティを 'color' に変更する、配列を平坦化するなど、いくつかの一般的な要件を簡単に満たすことができるからです。あるサービス/ライブラリからオブジェクトを受け取り、別の場所で必要な新しいオブジェクトを構築するときに必要なこと。アンダースコア/ロダッシュは優れた、適切に実装されたライブラリですが、これはベンダーへの依存度を下げるための私の推奨アプローチであり、サブセット構築ロジックがより複雑になったときのよりシンプルで一貫性のあるアプローチです。

編集:同じのes7バージョン:

const subset = ['color', 'height'].reduce((a, e) => (a[e] = elmo[e], a), {});

編集: カリー化の良い例でもあります! 'pick' 関数が別の関数を返すようにします。

const pick = (...props) => o => props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});

上記は、その場で「ピッカー」を作成できることを除いて、他の方法にかなり似ています。例えば

pick('color', 'height')(elmo);

このアプローチで特に優れているのは、選択した「ピック」を関数を取るものに簡単に渡すことができることですArray#map

[elmo, grover, bigBird].map(pick('color', 'height'));
// [
//   { color: 'red', height: 'short' },
//   { color: 'blue', height: 'medium' },
//   { color: 'yellow', height: 'tall' },
// ]
于 2015-08-24T13:54:04.877 に答える
13

ロダッシュも使えます。

var subset = _.pick(elmo ,'color', 'height');

補足として、「elmo」の配列があるとしましょう:

elmos = [{ 
      color: 'red',
      annoying: true,
      height: 'unknown',
      meta: { one: '1', two: '2'}
    },{ 
      color: 'blue',
      annoying: true,
      height: 'known',
      meta: { one: '1', two: '2'}
    },{ 
      color: 'yellow',
      annoying: false,
      height: 'unknown',
      meta: { one: '1', two: '2'}
    }
];

同じ動作が必要な場合は、lodash を使用して次のようにします。

var subsets = _.map(elmos, function(elm) { return _.pick(elm, 'color', 'height'); });
于 2014-08-06T12:12:02.067 に答える
7

既に使用pickしている場合は、lodash ライブラリのメソッドを使用します。

var obj = { 'a': 1, 'b': '2', 'c': 3 };

_.pick(object, ['a', 'c']);

// => { 'a': 1, 'c': 3 }

https://lodash.com/docs/4.17.10#pick

于 2018-07-27T06:13:42.363 に答える
2
  1. 引数を配列に変換する

  2. Array.forEach()プロパティを選択するために使用します

    Object.prototype.pick = function(...args) {
       var obj = {};
       args.forEach(k => obj[k] = this[k])
       return obj
    }
    var a = {0:"a",1:"b",2:"c"}
    var b = a.pick('1','2')  //output will be {1: "b", 2: "c"}
    
于 2016-09-22T16:17:42.223 に答える
2

どうですか:

function sliceObj(obj) {
  var o = {}
    , keys = [].slice.call(arguments, 1);
  for (var i=0; i<keys.length; i++) {
    if (keys[i] in obj) o[keys[i]] = obj[keys[i]];
  }
  return o;
}

var subset = sliceObj(elmo, 'color', 'height');
于 2013-07-22T06:53:21.690 に答える
2

このスレッドのいくつかのように、これを行うための最も明白な古い学校の方法が実際に利用可能な最良のものであることに同意しますが、楽しみのために、特定の状況でそれを行うための別の推奨されない方法を提供させてください。たとえば、サブセットが既に定義されている場合などです。また、プロパティのスーパーセットまたは交差するセットを含む別のオブジェクトからプロパティをコピーする場合。

let set = { a : 1, b : 2, c : 3 };
let subset = { a : null, b : null };
try {
  Object.assign(Object.seal(subset), set);
} catch (e) {
  console.log('its ok I meant to do that <(^.^)^');
}
console.log(subset);

于 2021-06-22T17:00:00.663 に答える
0

組み込みプロトタイプの拡張には利点があります。使用する場合Object.defineProperty、汚染は発生しません-残っている唯一の懸念は、将来のプロパティとの競合です(たとえばObject.prototype.slice、を定義し、将来、ES標準はObject.prototype.slice異なる機能を持つと定義します-今、あなたのコードは、想定されている意図された機能を破壊していますに存在しObject.prototype.sliceます)。

また...... ....... 。... .. ..... エルモの身長は不明ではない(!!!)

Object.defineProperty(Object.prototype, 'slice', {
  enumerable: false,
  writable: true,
  value: function(...args) {
    let o = {};
    for (let k of args) this.hasOwnProperty(k) && (o[k] = this[k]);
    return o;
  }
});

elmo = { 
  color: 'red',
  annoying: true,
  height: '24in',
  meta: { one: '1', two: '2'}
};

console.log(elmo.slice('color', 'height'));

于 2021-11-18T08:20:52.370 に答える
0

私の 2 セントをIvan Nosovの回答に追加します。

私の場合、オブジェクトから「スライス」するために多くのキーが必要だったので、非常に速く醜くなり、非常に動的なソリューションではなくなりました。

const object = { a: 5, b: 6, c: 7, d: 8, aa: 5, bb: 6, cc: 7, dd: 8, aaa: 5, bbb: 6, ccc: 7, ddd: 8, ab: 5, bc: 6, cd: 7, de: 8  };
const picked = (({ a, aa, aaa, ab, c, cc, ccc, cd }) => ({ a, aa, aaa, ab, c, cc, ccc, cd }))(object);

console.log(picked);

したがって、evalを使用した動的ソリューションは次のとおりです。

const slice = (k, o) => eval(`(${k} => ${k})(o)`);


const object    = { a: 5, b: 6, c: 7, d: 8, aa: 5, bb: 6, cc: 7, dd: 8, aaa: 5, bbb: 6, ccc: 7, ddd: 8, ab: 5, bc: 6, cd: 7, de: 8  };
const sliceKeys = '({ a, aa, aaa, ab, c, cc, ccc, cd })';

console.log( slice(sliceKeys, object) );
于 2019-12-16T13:21:57.313 に答える
-3

注:元の質問はjavascriptに関するものでしたが、以下のソリューションでjQueryを実行できます

必要に応じて jquery を拡張できます。これは、1 つのスライスのサンプル コードです。

jQuery.extend({
  sliceMe: function(obj, str) {
      var returnJsonObj = null;
    $.each( obj, function(name, value){
        alert("name: "+name+", value: "+value);
        if(name==str){
            returnJsonObj = JSON.stringify("{"+name+":"+value+"}");
        }

    });
      return returnJsonObj;
  }
});

var elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};


var temp = $.sliceMe(elmo,"color");
alert(JSON.stringify(temp));

ここに同じフィドルがあります:http://jsfiddle.net/w633z/

于 2013-07-22T07:07:34.023 に答える