web-dev-qa-db-ja.com

ES 6のオブジェクトからいくつかのプロパティを取得するためのワンライナー

ES6で最もコンパクトな方法で少数の属性のみを使用する関数を作成するにはどうすればよいですか?

私は、解体+単純化されたオブジェクトリテラルを使用したソリューションを考え出しましたが、コード内でフィールドのリストが繰り返されるのは好きではありません。

さらにスリムなソリューションはありますか?

(v) => {
    let { id, title } = v;
    return { id, title };
}
140
kirilloid

これはよりスリムなものですが、フィールドのリストを繰り返すことを避けません。 vパラメーターの必要性を回避するために、「パラメーターの分解」を使用します。

({id, title}) => ({id, title})

(この その他の回答 の実行可能な例を参照してください)。

@EthanBrownのソリューションはより一般的です。 Object.assignと計算されたプロパティ([p]部分)を使用する、より慣用的なバージョンを次に示します。

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

configurableやgetterおよびsetterなどのプロパティの属性を保持し、列挙不可能なプロパティも省略したい場合:

function pick(o, ...props) {
    var has = p => o.propertyIsEnumerable(p),
        get = p => Object.getOwnPropertyDescriptor(o, p);

    return Object.defineProperties({},
        Object.assign({}, ...props
            .filter(prop => has(prop))
            .map(prop => ({prop: get(props)})))
    );
}
111
user663031

あなたの答え(またはトラズブロ)よりもはるかにコンパクトにする方法はないと思いますが、基本的にあなたがしようとしているのはエミュレートすることです アンダースコアのpick操作 。 ES6でそれを再実装するのは簡単です:

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

次に、便利な再利用可能な関数があります:

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
42
Ethan Brown

これをワンライナーとして解決するコツは、取ったアプローチを逆にすることです。元のオブジェクトorigから開始する代わりに、抽出したいキーから開始できます。

Array#reduce を使用すると、上記の関数のinitialValueとして渡される空のオブジェクトに必要な各キーを格納できます。

そのようです:

const orig = {
  id: 123456789,
  name: 'test',
  description: '…',
  url: 'https://…',
};

const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});

console.log(filtered); // Object {id: 123456789, name: "test"}
19
Bramus

カンマ演算子を使用した少し短いソリューション:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
11
shesek

TC39のオブジェクトレスト/スプレッドプロパティの提案 は、これを非常に滑らかにします。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }

(必要ないかもしれないxおよびy変数を作成するという欠点があります。)

8
alxndr

オブジェクトの構造化を使用して、既存のオブジェクトからプロパティをアンパックし、 異なる名前の変数に割り当てます -最初は空の新しいオブジェクトのフィールド。

const person = {
  fname: 'tom',
  lname: 'jerry',
  aage: 100,
}

let newPerson = {};

({fname: newPerson.fname, lname: newPerson.lname} = person);

console.log(newPerson);
2
Saksham

現在、JavaScriptのオブジェクトの短縮構文を改善するための strawmanの提案 があります。これにより、名前なしプロパティを「ピッキング」することができます。

const source = {id: "68646", genre: "crime", title: "Scarface"};
const target = {};
Object.assign(target, {source.title, source.id});

console.log(picked);
// {id: "68646", title: "Scarface"}

残念ながら、この提案はすぐにはどこにも行きません。最終編集は2017年7月で、まだ Stage のドラフトであり、著者がそれを捨てたか忘れた可能性があることを示唆しています。

ES5以前(非厳密モード)

私が考えることができる簡潔な可能な省略表現には、 古代言語機能 誰ももう使用していません:

Object.assign(target, {...(o => {
    with(o) return { id, title };
})(source)});

withステートメントはストリクトモードでは禁止されているため、このアプローチは現代のJavaScriptの99.999%で役に立たなくなります。これは、with機能に対して私が見つけた中途半端な使用法だからです。 ????

1
user458541

ES6は、質問が書かれた当時の最新の仕様でした。 この回答 で説明されているように、ES2019のキー選択はES6よりも大幅に短くなっています。

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)
1
Estus Flask

Ethan Brownのソリューションと似ていますが、さらに短い-pick関数です。別の関数pick2は少し長く(そして遅く)なりますが、ES6の方法と同様にプロパティの名前を変更できます。

const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})

const pick2 = (o, ...props) => props.reduce((r, expr) => {
  const [p, np] = expr.split(":").map( e => e.trim() )
  return p in o ? {...r, [np || p]: o[p]} : r
}, {}) 

以下に使用例を示します。

const d = { a: "1", c: "2" }

console.log(pick(d, "a", "b", "c"))        // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
1

私はこのソリューションを必要としましたが、提案されたキーが利用可能かどうかは知りませんでした。だから、@ torazaburoの回答を取り、私のユースケースのために改善しました:

function pick(o, ...props) {
  return Object.assign({}, ...props.map(prop => {
    if (o[prop]) return {[prop]: o[prop]};
  }));
}

// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }
0
Alwin Kesler

https://stackoverflow.com/users/865693/shesek のreduceアプローチに触発されました:

const pick = (orig, ...keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})

使用法:

pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear')の結果:{model: "F40", productionYear: 1987}

0
Kevin K.