So erhalten Sie eine Teilmenge der Eigenschaften eines Javascript-Objekts

423

Angenommen, ich habe ein Objekt:

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

Ich möchte ein neues Objekt mit einer Teilmenge seiner Eigenschaften erstellen.

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

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

Wie kann ich das erreichen?

Christian Schlensker
quelle
2
Die Underscore-Bibliothek hat viele Hilfsfunktionen wie diese. Schauen Sie sich das an: underscorejs.org/#pick
Stefan
4
Ich dachte, das sagte emo.sliceauf den ersten Blick.
Bill Criswell
1
Beim zweiten Gedanken ... Ich werde keine Teilmenge erstellen ...
Andrew

Antworten:

672

Verwenden von Objektzerstörung und Eigenschaftskürzel

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

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


Von Philipp Kewisch:

Dies ist wirklich nur eine anonyme Funktion, die sofort aufgerufen wird. All dies finden Sie auf der Seite Destructuring Assignment auf MDN. Hier ist eine erweiterte Form

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)

Ivan Nosov
quelle
37
Wie haben Sie gelernt, wie das geht? Nirgendwo in Dokumenten oder Artikeln, die ich gesehen habe (einschließlich MDN), wird die Pfeilsyntax angezeigt, die bei der Objektzerstörung verwendet wird. Das ist sehr schön zu wissen.
Papiro
52
Dies ist wirklich nur eine anonyme Funktion, die sofort aufgerufen wird. All dies finden Sie auf der Seite Destructuring Assignment auf MDN. Hier ist eine erweiterte Form: let unwrap = ({a, c}) => ({a, c}); let unwrap2 = function({a, c}) { return { a, c }; }; let picked = unwrap({ a: 5, b: 6, c: 7 });
Philipp Kewisch
8
Gibt es eine Möglichkeit, dies dynamisch mit dem Spread-Operator zu tun?
Tom Sarduy
4
@TomSarduy Sie Rest verwenden können , wenn Sie angeben möchten , welche entfernen Requisiten, zum Beispiel const { b, ...picked } = objectschaffen würde pickedwie { a: 5, c: 7 }. Sie haben angegeben, einfach zu entfernen b. Ihr Eslint wird Sie wahrscheinlich ärgern, wenn Sie eine Var deklarieren, die Sie nicht verwenden.
Josh von Qaribou
23
Ein Nachteil hierbei ist, dass Sie die Reihe der Attributnamen zweimal vollständig eingeben müssen. Dies kann in Fällen, in denen viele Attribute ausgewählt werden müssen, ein ziemliches Problem darstellen.
Gershom
144

Ich schlage vor, einen Blick auf Lodash zu werfen . Es hat viele großartige Utility-Funktionen.

Zum Beispiel pick()wäre genau das, was Sie suchen:

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

Geige

Ygg
quelle
2
Gleiches gilt für underscore.js
Dan
1
Gibt es eine Funktion, um nur bestimmte Felder auszuschließen, anstatt sie auszuwählen? Ich habe also ungefähr 50 Felder in meinem JSON und möchte alles außer nur 2 Feldern.
Shrikant Prabhu
7
ja! Sie können verwenden _.omit(elmo, ['voice']), um alles außervoice
xavdid
Was mir an diesem Ansatz nicht gefällt, ist, dass Sie die Feldnamen in Anführungszeichen setzen, damit sie für Tippfehler anfällig sind. Häufige Umgestaltungen wie das Umbenennen einer Eigenschaft in Ihrer IDE werden sie nicht aufgreifen usw. usw.
Andy
117

Wenn Sie ES6 verwenden, gibt es eine sehr präzise Möglichkeit, dies mithilfe der Destrukturierung zu tun. Durch die Destrukturierung können Sie Objekte mithilfe eines Spreads problemlos hinzufügen, aber auch Teilmengenobjekte auf die gleiche Weise erstellen.

const object = {
  a: 'a',
  b: 'b',
  c: 'c',
  d: 'd',
}

// Remove "c" and "d" fields from original object:
const {c, d, ...partialObject} = object;
const subset = {c, d};

console.log(partialObject) // => { a: 'a', b: 'b'}
console.log(subset) // => { c: 'c', d: 'd'};
Lauren
quelle
6
Dies funktioniert nur, um ein Feld zu entfernen, nicht um eine bekannte Teilmenge auszuwählen. Möglicherweise ist eine unendliche Anzahl unbekannter Felder zu entfernen, aber es könnte das sein, wonach einige Leute suchen
Alexander Mills
Es stimmt, aber es können mehrere bekannte Felder entfernt werden, die dann einem neuen Objekt zugewiesen werden können, sodass es sich für diese Frage immer noch relevant anfühlt. Zur weiteren Veranschaulichung zur Antwort hinzugefügt.
Lauren
1
Dies ist im Wesentlichen das Gleiche wie die Antwort von @Ivan Nosov , obwohl es hier verständlicher erklärt wird
icc97
81

Obwohl es etwas ausführlicher ist, können Sie mithilfe von Array.prototype.reduce das erreichen, was alle anderen vor 2 Jahren unterstrichen / lodash empfohlen haben .

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

Dieser Ansatz löst es von der anderen Seite: Anstatt ein Objekt zu nehmen und ihm Eigenschaftsnamen zum Extrahieren zu übergeben, nehmen Sie ein Array von Eigenschaftsnamen und reduzieren Sie sie in ein neues Objekt.

Während es im einfachsten Fall ausführlicher ist, ist ein Rückruf hier ziemlich praktisch, da Sie einige allgemeine Anforderungen leicht erfüllen können, z. B. die Eigenschaft 'color' für das neue Objekt in 'color' ändern, Arrays reduzieren usw. die Dinge, die Sie tun müssen, wenn Sie ein Objekt von einem Dienst / einer Bibliothek empfangen und ein neues Objekt erstellen, das an einem anderen Ort benötigt wird. Während Unterstriche / lodash ausgezeichnete, gut implementierte Bibliotheken sind, ist dies mein bevorzugter Ansatz für weniger Herstellerabhängigkeit und einen einfacheren, konsistenteren Ansatz, wenn meine Logik zum Erstellen von Teilmengen komplexer wird.

edit: es7 version desselben:

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

edit: Ein schönes Beispiel auch zum Curry! Lassen Sie eine 'Pick'-Funktion eine andere Funktion zurückgeben.

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

Das Obige kommt der anderen Methode ziemlich nahe, außer dass Sie damit im laufenden Betrieb einen "Picker" bauen können. z.B

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

Das Besondere an diesem Ansatz ist, dass Sie die ausgewählten "Picks" problemlos an alles übergeben können, was eine Funktion übernimmt, z Array#map.

[elmo, grover, bigBird].map(pick('color', 'height'));
// [
//   { color: 'red', height: 'short' },
//   { color: 'blue', height: 'medium' },
//   { color: 'yellow', height: 'tall' },
// ]
Josh aus Qaribou
quelle
3
es6 ermöglicht es, dass dies über Pfeilfunktionen und die Rückgabe von Object.assign noch sauberer wird (da die Zuweisung zu einer Objekteigenschaft den Eigenschaftswert zurückgibt, Object.assign jedoch das Objekt zurückgibt.)
Josh aus Qaribou
Ein weiterer Hinweis von es6: Sie müssen dies nur noch sehr selten tun, da Sie normalerweise nur Zuweisungen oder Argumente zerstören. zB function showToy({ color, height }) {würde nur das, was Sie brauchen, in den Geltungsbereich setzen. Der reduceAnsatz ist hauptsächlich dann sinnvoll, wenn Sie Objekte für die Serialisierung vereinfachen.
Josh von Qaribou
6
Diese ES6-Version ist weniger leistungsfähig, da bei jeder Iteration eine Kopie aller Eigenschaften erstellt wird. Es macht eine O (n) -Operation zu O (n ^ 2). Ein ES6-Äquivalent Ihres ersten Codeblocks wäreconst pick = (obj, props) => props.reduce((a, e) => (a[e] = obj[e], a), {});
4castle
@ 4castle yep guter Anruf - es macht keinen Sinn, so viel zu wiederholen. Ich mag die Kommasyntax - besser als eine Reihe von Rückgaben.
Josh von Qaribou
1
@ShevchenkoViktor Ich hatte diesen Ansatz tatsächlich in meiner ursprünglichen es6-Version verwendet, ihn aber nach dem Kommentar von @ 4castle geändert. Ich denke, die Streuung ist klarer, aber es ist ein großer Unterschied für größere Objekte im Code, die leicht zu einem Engpass führen können (z. B. Verzögerung der Wiedergabe von Rendering-Daten fetch). Daher würde ich empfehlen, einen Kommentar hinzuzufügen, der die Verwendung des Komma-Operators erklärt.
Josh aus Qaribou
44

ES6-Destrukturierung

Die Destrukturierungssyntax ermöglicht das Destrukturieren und Rekombinieren eines Objekts mit Funktionsparametern oder Variablen.

Die Einschränkung besteht darin, dass eine Liste von Schlüsseln vordefiniert ist. Sie können nicht als Zeichenfolgen aufgeführt werden, wie in der Frage erwähnt. Die Destrukturierung wird komplizierter, wenn ein Schlüssel nicht alphanumerisch ist, z foo_bar.

Der Nachteil ist, dass dies das Duplizieren einer Liste von Schlüsseln erfordert. Dies führt zu ausführlichem Code, falls eine Liste lang ist. Da die Destrukturierung in diesem Fall die Objektliteral-Syntax dupliziert, kann eine Liste unverändert kopiert und eingefügt werden.

Der Vorteil ist, dass es sich um eine performante Lösung handelt, die für ES6 selbstverständlich ist.

IIFE

let subset = (({ foo, bar }) => ({ foo, bar }))(obj); // dupe ({ foo, bar })

Temporäre Variablen

let { foo, bar } = obj;
let subset = { foo, bar }; // dupe { foo, bar }

Eine Liste von Zeichenfolgen

Die beliebige Liste der ausgewählten Schlüssel besteht je nach Frage aus Zeichenfolgen. Dies ermöglicht es, sie nicht vordefinieren und Variablen zu verwenden, die Schlüsselnamen enthalten, wie z pick(obj, 'foo', someKey, ...moreKeys).

Ein Einzeiler wird mit jeder JS-Ausgabe kürzer.

ES5

var subset = Object.keys(obj)
.filter(function (key) { 
  return ['foo', 'bar'].indexOf(key) >= 0;
})
.reduce(function (obj2, key) {
  obj2[key] = obj[key];
  return obj2;
}, {});

ES6

let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => Object.assign(obj2, { [key]: obj[key] }), {});

Oder mit Komma-Operator:

let subset = Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});

ES2019

ECMAScript 2017 hat Object.entriesund Array.prototype.includesECMAScript 2019 hat Object.fromEntries, sie können bei Bedarf polygefüllt werden und erleichtern die Aufgabe:

let subset = Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)

Ein Einzeilerpick kann als Hilfsfunktion ähnlich wie Lodash umgeschrieben werden oder omitwenn die Liste der Schlüssel über Argumente übergeben wird:

let pick = (obj, ...keys) => Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => keys.includes(key))
);

let subset = pick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1 }

Ein Hinweis zu fehlenden Schlüsseln

Der Hauptunterschied zwischen der Destrukturierung und der herkömmlichen Lodash-ähnlichen pickFunktion besteht darin, dass die Destrukturierung nicht vorhandene ausgewählte Schlüssel mit dem undefinedWert in einer Teilmenge enthält:

(({ foo, bar }) => ({ foo, bar }))({ foo: 1 }) // { foo: 1, bar: undefined }

Dieses Verhalten kann wünschenswert sein oder nicht. Es kann nicht für die Destrukturierungssyntax geändert werden.

Während pickkann geändert werden, um fehlende Schlüssel einzuschließen, indem stattdessen eine Liste der ausgewählten Schlüssel wiederholt wird:

let inclusivePick = (obj, ...keys) => Object.fromEntries(
  keys.map(key => [key, obj[key]])
);

let subset = inclusivePick({ foo: 1, qux: 2 }, 'foo', 'bar'); // { foo: 1, bar: undefined }
Estus Flask
quelle
11
Was für eine Schande, dass diese Antwort so neu ist und daher nicht die Belichtung erhält, die sie verdient. IMO sollte es die akzeptierte Antwort für Vollständigkeit, Einfachheit, Vielseitigkeit und Gerechtigkeit sein. Ich werde die ES6-Version in meiner nützlichsten Snippet-Bibliothek behalten.
VanAlbert
ES5 - "Ungefangener Referenzfehler: obj ist nicht definiert"
Nikhil Vartak
@NikhilVartak Es wird erwartet, dass die objVariable eine Variable ist, die ein Objekt speichert. Wenn sich Ihr Variablenname unterscheidet, verwenden Sie ihn anstelle von obj.
Estus Flask
Mein Fehler! Ich habe übersehen Object.keys(obj). Schläfrig.
Nikhil Vartak
34

In der Kernbibliothek ist nichts Vergleichbares integriert, aber Sie können die Objektzerstörung verwenden, um dies zu tun ...

const {color, height} = sourceObject;
const newObject = {color, height};

Sie können auch ein Dienstprogramm schreiben, um es zu tun ...

const cloneAndPluck = function(sourceObject, keys) {
    const newObject = {};
    keys.forEach((obj, key) => { newObject[key] = sourceObject[key]; });
    return newObject;
};

const subset = cloneAndPluck(elmo, ["color", "height"]);

Bibliotheken wie Lodash haben auch _.pick().

Alex
quelle
1
toll, ich musste nur forEach ändern in: keys.forEach (key => {newObject [key] = sourceObject [key];});. Bitte aktualisieren Sie den Kommentar, wenn dies sinnvoll ist.
Kandan
33

Ich füge diese Antwort hinzu, weil keine der Antworten verwendet wurde Comma operator.

Es ist sehr einfach mit destructuring assignmentund ,Bediener

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

console.log(picked);

Mit einer gewissen Verbesserung für die Zuweisung dynamischer Eigenschaften könnte dies folgendermaßen aussehen:

Code Maniac
quelle
2
mein schlechtes, ich weiß nicht, was ich vorher getan habe, dass es nicht funktioniert hat, aber es scheint zu funktionieren
ekkis
1
Das ist der beste Ausdruck, wenn es um Destrukturierung geht
Mohamed Allal
1
Diese Lösung ist clever, funktioniert aber nicht im strengen Modus (dh 'use strict'). Ich bekomme eine ReferenceError: a is not defined.
Kimbaudi
8
Beachten Sie, dass dieser Ansatz den aktuellen Bereich mit zwei Variablen verschmutzt aund c- achten Sie darauf, lokale oder globale Variablen je nach Kontext nicht zufällig zu überschreiben. (Die akzeptierte Antwort vermeidet dieses Problem, indem zwei lokale Variablen in einer Inline-Funktion verwendet werden, die nach sofortiger Ausführung nicht mehr in den Geltungsbereich fällt.)
mindplay.dk
2
Die Verschmutzung des Namespace macht dies völlig unpraktisch. Es ist sehr häufig, dass bereits Variablen im Gültigkeitsbereich vorhanden sind, die mit den Objekteigenschaften übereinstimmen. Aus diesem Grund ist die Prop-Kurzschrift + Destrukturierung vorhanden. Sehr wahrscheinlich ist bereits eine Höhe oder Farbe wie im ursprünglichen Beispiel definiert.
Josh aus Qaribou
23

Noch eine Lösung:

var subset = {
   color: elmo.color,
   height: elmo.height 
}

Das sieht für mich weitaus lesbarer aus als so ziemlich jede Antwort bisher, aber vielleicht bin das nur ich!

Evert
quelle
9
Ich bin lieber produktiv als ausgefallener, aber verwirrender Code, und in der realen Softwareentwicklung ist dies bei weitem die am besten lesbare und wartbarste Lösung.
Janos
1
Ja, für mich ist ein Vorteil der Verwendung von Destrukturierung und Kurzschreibweise, dass sie weniger fehleranfällig ist. Wenn ich für jedes Mal einen Cent gehabt hätte, wenn ich fälschlicherweise Code kopiert und eingefügt subset = {color: elmo.color, height: elmo.color}hätte, hätte ich mindestens einen ... na ja, vielleicht einen Cent gehabt.
JHH
Ich würde die Destrukturierungskürzel nicht als weniger fehleranfällig bezeichnen, da sie nicht
trocken ist
Ich müsste zustimmen. Ohne den Kontext mit unerwünschten Variablen zu verschmutzen, ist dies bei weitem die am besten lesbare Lösung. Der Rest sieht viel zu verwirrend aus. Ich ziehe es vor, meinen Code zu verstehen, sobald ich ihn mir ansehe.
Andrew
11

Sie können auch Lodash verwenden .

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

Nehmen wir an, Sie haben eine Reihe von "Elmos":

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'}
    }
];

Wenn Sie dasselbe Verhalten mit lodash wünschen, würden Sie einfach:

var subsets = _.map(elmos, function(elm) { return _.pick(elm, 'color', 'height'); });
Arthur Alvim
quelle
10

Die Destrukturierung in dynamisch benannte Variablen ist in JavaScript nicht möglich, wie in dieser Frage erläutert .

Um Schlüssel dynamisch zu setzen , können Sie die Reduzierungsfunktion verwenden, ohne das Objekt wie folgt zu mutieren:

const getSubset = (obj, ...keys) => keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});

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

const subset = getSubset(elmo, 'color', 'annoying')
console.log(subset)

Beachten Sie jedoch, dass Sie bei jeder Iteration ein neues Objekt erstellen, anstatt einen einzelnen Klon zu aktualisieren. - mpen

Im Folgenden finden Sie eine Version, bei der Reduzieren mit einem einzelnen Klon verwendet wird (Aktualisieren des zur Reduzierung übergebenen Anfangswertes).

const getSubset = (obj, ...keys) => keys.reduce((acc, curr) => {
  acc[curr] = obj[curr]
  return acc
}, {})

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

const subset = getSubset(elmo, 'annoying', 'height', 'meta')
console.log(subset)

Muhammet Enginar
quelle
1
Genial! Es warf mich für einen Moment nicht zu erkennen, wie wichtig die Klammern auf [c] sind :. Ich gehe davon aus, dass dies irgendwie dazu führt, dass c als Wert anstelle des Namens der Eigenschaft betrachtet wird. Wie auch immer, sehr cool. +1
John Fairbanks
Danke Kumpel! Diese Verwendung ist eine Sache, die ich an JavaScript liebe, die generische Funktionen ohne Verwendung von eval ermöglicht. Sie können damit einfach einen Diktatschlüssel für eine Variable zur Laufzeit festlegen. Wenn Sie var key = 'someKey' definieren, können Sie es als {[key]: 'value'} verwenden, wodurch Sie {someKey: 'value'} erhalten. Wirklich cool.
Muhammet Enginar
1
Beachten Sie jedoch, dass Sie bei jeder Iteration ein neues Objekt erstellen, anstatt einen einzelnen Klon zu aktualisieren.
Mpen
1
@mpen guter Fund. Ich habe eine Version hinzugefügt, die einen einzelnen Klon mutiert, da Sie vorgeschlagen haben, auch Argumente zu verbreiten, anstatt ein Array von Schlüsseln zu übergeben.
Muhammet Enginar
7

TypeScript-Lösung:

export function pick<T extends object, U extends keyof T>(obj: T, paths: Array<U>) {
    return paths.reduce((o, k) => {
        o[k] = obj[k];
        return o;
    }, Object.create(null));
}

Die Tippinformationen ermöglichen sogar die automatische Vervollständigung:

Dank an DefinitelyTyped für U extends keyof TTrick!

mpen
quelle
Ich arbeite nicht für mich.
Nuthinking
@Nuthinking Verwenden Sie VS-Code?
Mpen
Ja, ich benutze VS Code.
Nuthinking
@Nuthinking Und du hast das in eine .ts-Datei geschrieben? Das sollte funktionieren. Ich habe es gerade noch einmal versucht
Uhr
5

Verwenden Sie die pickMethode der lodash-Bibliothek, wenn Sie sie bereits verwenden.

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

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

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

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

Kashif Nazar
quelle
4

Dynamische Lösung

['color', 'height'].reduce((a,b) => (a[b]=elmo[b],a), {})

Kamil Kiełczewski
quelle
3

Nur ein anderer Weg ...

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

var subset = [elmo].map(x => ({
  color: x.color,
  height: x.height
}))[0]

Sie können diese Funktion mit einem Array von Objekten verwenden =)

Arthur Araújo
quelle
2

Wie wäre es mit:

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');
elclanrs
quelle
Dies würde fehlschlagen, wenn der Wert der Eigenschaft false(oder falsch) wäre. jsfiddle.net/nfAs8
Alxandr
Deshalb habe ich es geändert keys[i] in obj.
Elclanrs
2

Dies funktioniert bei mir in der Chrome-Konsole. Irgendein Problem damit?

var { color, height } = elmo
var subelmo = { color, height }
console.log(subelmo) // {color: "red", height: "unknown"}
MSi
quelle
4
Das liest sich gut, erzeugt aber zwei unnötige Variablen, Farbe und Höhe.
user424174
Verstehe deinen Kommentar nicht. Die Anforderung von OP bestand darin, ein Objekt mit diesen beiden Elementen zu erstellen
MSi
@MSi Dies erstellt nicht nur ein Objekt, sondern auch zwei Variablen.
Entwurf durch Adrian
1

Destrukturierungszuordnung mit dynamischen Eigenschaften

Diese Lösung gilt nicht nur für Ihr spezifisches Beispiel, sondern ist allgemeiner anwendbar:

const subset2 = (x, y) => ({[x]:a, [y]:b}) => ({[x]:a, [y]:b});

const subset3 = (x, y, z) => ({[x]:a, [y]:b, [z]:c}) => ({[x]:a, [y]:b, [z]:c});

// const subset4...etc.


const o = {a:1, b:2, c:3, d:4, e:5};


const pickBD = subset2("b", "d");
const pickACE = subset3("a", "c", "e");


console.log(
  pickBD(o), // {b:2, d:4}
  pickACE(o) // {a:1, c:3, e:5}
);

Sie können subset4usw. leicht definieren , um mehr Eigenschaften zu berücksichtigen.


quelle
1

Gut alt Array.prototype.reduce:

const selectable = {a: null, b: null};
const v = {a: true, b: 'yes', c: 4};

const r = Object.keys(selectable).reduce((a, b) => {
  return (a[b] = v[b]), a;
}, {});

console.log(r);

Diese Antwort verwendet den magischen Komma-Operator, außerdem: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

Wenn Sie wirklich ausgefallen werden möchten, ist dies kompakter:

const r = Object.keys(selectable).reduce((a, b) => (a[b] = v[b], a), {});

Alles zu einer wiederverwendbaren Funktion zusammenfügen:

const getSelectable = function (selectable, original) {
  return Object.keys(selectable).reduce((a, b) => (a[b] = original[b], a), {})
};

const r = getSelectable(selectable, v);
console.log(r);
Alexander Mills
quelle
1
  1. Argumente in Array konvertieren

  2. Verwenden Sie Array.forEach(), um die Eigenschaft auszuwählen

    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"}
Olivia
quelle
4
Das Erweitern des Prototyps nativer Typen wird als schlechte Praxis angesehen, obwohl es funktionieren würde. Tun Sie dies nicht, wenn Sie eine Bibliothek schreiben.
Emile Bergeron
0
function splice()
{
    var ret = new Object();

    for(i = 1; i < arguments.length; i++)
        ret[arguments[i]] = arguments[0][arguments[i]];

    return ret;
}

var answer = splice(elmo, "color", "height");
John
quelle
0

Versuchen

const elmo={color:"red",annoying:!0,height:"unknown",meta:{one:"1",two:"2"}};

const {color, height} = elmo; newObject = ({color, height});

console.log(newObject); //{ color: 'red', height: 'unknown' }
Mohan Kumar
quelle
0

Hinzufügen meiner 2 Cent zu Ivan Nosov Antwort:

In meinem Fall brauchte ich viele Schlüssel, um aus dem Objekt herausgeschnitten zu werden, damit es sehr schnell hässlich wird und keine sehr dynamische Lösung ist:

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);

Hier ist also eine dynamische Lösung mit 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) );
Igor
quelle
-2

Hinweis: Obwohl die ursprünglich gestellte Frage Javascript betraf, kann jQuery mit der folgenden Lösung durchgeführt werden

Sie können jquery erweitern, wenn Sie möchten. Hier ist der Beispielcode für ein Slice:

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));

Hier ist die Geige dafür: http://jsfiddle.net/w633z/

ManMohan Vyas
quelle
16
Was ist jquery?
Christian Schlensker
1
@ChristianSchlensker es ist Javascript
Kevin B