2013-09-26 28 views
103

Funkcja map w pliku underscore.js, wywołana z obiektem javascript, zwraca tablicę wartości odwzorowanych z wartości obiektu.Mapa nad kluczami zachowującymi obiekty

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

Czy istnieje sposób na zachowanie kluczy? tj. chcę funkcji, która zwraca

{one: 3, two: 6, three: 9} 
+0

Jeśli, tak jak ja, przybył tu w poszukiwaniu podobnego funkcji „mapValues”, który zmienia rzeczywisty obiekt zamiast wrócić nowego, sprawdzić to proste rozwiązanie na: http: // stackoverflow. com/questions/30894044/destructively-map-object-properties-function- –

Odpowiedz

178

Z Podkreślenie

Podkreślenie zapewnia funkcję _.mapObject do mapowania wartości i zachowania klawiszy.

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

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

DEMO


Z Lodash

Lodash zapewnia funkcję _.mapValues do mapowania wartości i zachowania klawiszy.

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

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

DEMO

+0

dzięki! Widziałem tę funkcję i myśl o czymś takim, ale zastanawiałem się, czy istnieje bardziej bezpośredni sposób mapowania obiektu. – xuanji

+0

Podjęto wysiłki, aby uzyskać _.Parametry mapValues ​​w podkreśleniu: [relewancja] (https://github.com/jashkenas/underscore/issues/220), [Pull Request for _.mapValues] (https://github.com/jashkenas/underscore/pull/ 1953). Mam nadzieję, że to minie :) – raffomania

+0

Wydaje mi się, że robisz PRZEDMIOT w obiekcie, czy też nie rozumiem? – jsh

3

zwraca tablicę, a nie obiekt.

Jeśli chcesz uzyskać lepszy przedmiot, użyj innej funkcji, np. each; Jeśli naprawdę chcesz korzystać z mapy można zrobić coś takiego:

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

ale to mylące, widząc map można by spodziewać się, że w wyniku tablicę, a następnie zrobić coś z nim.

+0

Miałem przeczucie czytając dokumenty, że nie byłoby naturalne, aby spróbować to w pliku underscore.js. Myślę, że mój przypadek użycia jest całkiem naturalny, dlaczego go nie wspierają? – xuanji

+0

Jednym z powodów może być to, że 'map' jest używana do zmiany danych wejściowych tworzących tablicę jako dane wyjściowe, możesz skomponować' _.object' i '_.map' jako @GG. napisał, ale to kwestia gustu w tym momencie. –

2

myślę chcesz mapValues function (mapowanie funkcji stosunku wartości obiektu), co jest dość łatwe do wdrożenia siebie:

mapValues = function(obj, f) { 
    var k, result, v; 
    result = {}; 
    for (k in obj) { 
    v = obj[k]; 
    result[k] = f(v); 
    } 
    return result; 
}; 
52

Udało mi się znaleźć wymaganą funkcję w lodash, bibliotece narzędziowej podobnej do podkreślenia.

http://lodash.com/docs#mapValues

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

Tworzy obiekt z tych samych kluczy jako przedmiotu i wartości generowanych przez systemem każdy właścicielem enumerable własności obiektu poprzez zwrotnego. Połączenie zwrotne jest powiązane z tymArg i wywoływane trzema argumentami; (wartość, klucz, obiekt).

17

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>

1

Mieszanka fix na mapie podkreślenia bug: 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; 
    } 
}); 

Proste rozwiązania alternatywnego, który utrzymuje odpowiedni klucz i wrócić jako przedmiot It jest nadal używany w taki sam sposób, jak i gość, możesz użyć tej funkcji zastąpić funkcję Bugy _.map

lub po prostu jak ja stosować ją jako wstawek

_.mapobj (options , function(val, key, list) 
13

wiem, że to jest stary, ale teraz Podkreślenie ma nową mapę do obiektów:

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

można oczywiście zbudować elastyczne mapy dla obu tablic i obiektów

_.fmap = function(arrayOrObject, fn, context){ 
    if(this.isArray(arrayOrObject)) 
     return _.map(arrayOrObject, fn, context); 
    else 
     return _.mapObject(arrayOrObject, fn, context); 
} 
+4

Uwaga dla użytkowników: jdalton zdecydował się [złamać kompatybilność z underscore.js] (https://github.com/lodash/lodash/issues/980) nad tą zmianą. lodash nie obsługuje 'mapObject'; zamiast tego spójrz na metodę 'mapValues'. –

7

Jak abo ut tej wersji w zwykłym JS (ES6/ES2015)?

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

jsbin

Jeśli chcesz mapować nad obiektem rekurencyjnie (map zagnieżdżony OBJ), można to zrobić tak:

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

Od ES7/ES2016 możesz użyć Object.entries zamiast Object.keys jak ten:

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

wiem, że to było dawno, ale wciąż najbardziej oczywiste rozwiązanie poprzez krotnie (aka zmniejszyć w js) brakuje, dla kompletności wywodu będę zostawić go tutaj:

function mapO(f, o) { 
    return Object.keys(o).reduce((acc, key) => { 
    acc[key] = f(o[key]) 
    return acc 
    }, {}) 
}