Zuordnung von Objektbewahrungsschlüsseln

129

Die mapFunktion in underscore.js gibt, wenn sie mit einem Javascript-Objekt aufgerufen wird, ein Array von Werten zurück, die aus den Werten des Objekts zugeordnet sind.

_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]

Gibt es eine Möglichkeit, die Schlüssel zu erhalten? dh ich möchte eine Funktion, die zurückgibt

{one: 3, two: 6, three: 9}
Xuanji
quelle
Wenn Sie wie ich hierher gekommen sind, um nach einer 'mapValues'-ähnlichen Funktion zu suchen, die das eigentliche Objekt ändert, anstatt ein neues zurückzugeben, sehen Sie sich diese einfache Lösung an: stackoverflow.com/questions/30894044/…
Michael Trouw

Antworten:

228

Mit Unterstrich

Der Unterstrich bietet eine Funktion _.mapObjectzum Zuordnen der Werte und zum Beibehalten der Schlüssel.

_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO


Mit Lodash

Lodash bietet eine Funktion _.mapValueszum Zuordnen der Werte und zum Beibehalten der Schlüssel.

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

DEMO

GG.
quelle
Es wurden Anstrengungen unternommen, um eine _.mapValues-Funktion in den Unterstrich zu bringen: Relevantes Problem , Pull-Anforderung für _.mapValues . Ich hoffe das geht durch :)
Raffomania
es sieht für mich so aus, als würdest du ein OBJEKT in ein Objekt verwandeln, oder bin ich verrückt?
Jsh
@jsh In diesem Fall _.map()wird zurückgegeben [['one', 3], ['two', 6], ['three', 9]], bei dem es sich um ein Array von Arrays handelt, und _.object()es wird wieder in ein Objekt umgewandelt.
Jezen Thomas
56

Ich habe es geschafft, die erforderliche Funktion in lodash zu finden, einer Utility-Bibliothek, die dem Unterstrich ähnelt.

http://lodash.com/docs#mapValues

_.mapValues(object, [callback=identity], [thisArg])

Erstellt ein Objekt mit denselben Schlüsseln wie Objekt und Werten, die durch Ausführen jeder eigenen aufzählbaren Eigenschaft des Objekts über den Rückruf generiert werden. Der Rückruf ist an thisArg gebunden und wird mit drei Argumenten aufgerufen. (Wert, Schlüssel, Objekt).

Xuanji
quelle
19

var mapped = _.reduce({ one: 1, two: 2, three: 3 }, function(obj, val, key) {
    obj[key] = val*3;
    return obj;
}, {});

console.log(mapped);
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

Kunalgolani
quelle
13

Ich weiß, dass dies alt ist, aber jetzt hat Underscore eine neue Karte für Objekte:

_.mapObject(object, iteratee, [context]) 

Sie können natürlich eine flexible Karte für Arrays und Objekte erstellen

_.fmap = function(arrayOrObject, fn, context){
    if(this.isArray(arrayOrObject))
      return _.map(arrayOrObject, fn, context);
    else
      return _.mapObject(arrayOrObject, fn, context);
}
Rayjax
quelle
5
Hinweis für Benutzer von lodash: jdalton hat beschlossen, die Kompatibilität mit underscore.js wegen dieser Änderung zu unterbrechen . lodash wird nicht unterstützen mapObject; Schauen Sie sich stattdessen die mapValuesMethode von lodash an .
Mark Amery
13

Wie wäre es mit dieser Version in einfachem JS ( ES6 / ES2015 )?

let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));

jsbin

Wenn Sie ein Objekt rekursiv zuordnen möchten (verschachteltes Objekt zuordnen), können Sie dies folgendermaßen tun:

const mapObjRecursive = (obj) => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'object') obj[key] = mapObjRecursive(obj[key]);
    else obj[key] = obj[key] * 3;
  });
  return obj;
};

jsbin

Seit ES7 / ES2016 können Sie Object.entriesstattdessen Folgendes verwenden Object.keys:

let newObj = Object.assign(...Object.entries(obj).map([k, v] => ({[k]: v * 3})));
Rotareti
quelle
5

Ich weiß, es ist lange her, aber es fehlt immer noch die naheliegendste Lösung über Fold (auch bekannt als Reduzieren in js). Der Vollständigkeit halber werde ich sie hier belassen:

function mapO(f, o) {
  return Object.keys(o).reduce((acc, key) => {
    acc[key] = f(o[key])
    return acc
  }, {})
}
Darwin
quelle
Ich bin mit der Verwendung der Lodash-Bibliothek einverstanden, aber Programmierer verwenden diese Art von Bibliotheken und wissen nicht, wie dies in Vanilla JS erreicht werden kann. Ich freue mich über Ihre Antwort!
Cyonder
3

_.map gibt ein Array zurück, kein Objekt.

Wenn Sie ein Objekt möchten, sollten Sie eine andere Funktion verwenden, z each. Wenn Sie wirklich eine Karte verwenden möchten, können Sie Folgendes tun:

Object.keys(object).map(function(value, index) {
   object[value] *= 3;
})

aber das ist verwirrend, wenn man sieht map, dass man ein Array als Ergebnis erwartet und dann etwas daraus macht.

Alberto Zaccagni
quelle
Ich hatte das Gefühl, als ich die Dokumente las, dass es nicht selbstverständlich wäre, dies in underscore.js zu versuchen. Ich denke, mein Anwendungsfall ist ganz natürlich. Warum unterstützen sie ihn nicht?
Xuanji
Ein Grund könnte wahrscheinlich sein, dass mapverwendet wird, um eine Eingabe zu ändern, die ein Array als Ausgabe erzeugt, die Sie komponieren _.objectund _.mapals @GG. schrieb, aber das ist an dieser Stelle Geschmackssache.
Alberto Zaccagni
3

Ich denke, Sie möchten eine mapValues- Funktion (um eine Funktion über die Werte eines Objekts abzubilden), die einfach genug ist, um sich selbst zu implementieren:

mapValues = function(obj, f) {
  var k, result, v;
  result = {};
  for (k in obj) {
    v = obj[k];
    result[k] = f(v);
  }
  return result;
};
Joyrexus
quelle
2
const mapObject = (obj = {}, mapper) =>
  Object.entries(obj).reduce(
    (acc, [key, val]) => ({ ...acc, [key]: mapper(val) }),
    {},
  );
Nigel Kirby
quelle
Ich wollte diese Antwort selbst hinzufügen. Ich bin froh, dass ich gescrollt habe!
Bill Criswell
0

Ein Mix-Fix für den Unterstrich-Map- Fehler : P.

_.mixin({ 
    mapobj : function( obj, iteratee, context ) {
        if (obj == null) return [];
        iteratee = _.iteratee(iteratee, context);
        var keys = obj.length !== +obj.length && _.keys(obj),
            length = (keys || obj).length,
            results = {},
            currentKey;
        for (var index = 0; index < length; index++) {
          currentKey = keys ? keys[index] : index;
          results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
        }
        if ( _.isObject( obj ) ) {
            return _.object( results ) ;
        } 
        return results;
    }
}); 

Eine einfache Problemumgehung, bei der der richtige Schlüssel beibehalten und als Objekt zurückgegeben wird. Sie wird immer noch genauso verwendet wie ich als Gast. Mit dieser Funktion können Sie die fehlerhafte Funktion _.map überschreiben

oder einfach so wie ich es als Mixin benutzt habe

_.mapobj ( options , function( val, key, list ) 
Pascal
quelle