Карта над ключами сохранения объектов
Функция map
в underscore.js, если вызвана с объектом javascript, возвращает массив значений, отображенных из значений объекта.
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]
Есть ли способ сохранить ключи? т.е. я хочу функцию, которая возвращает
{one: 3, two: 6, three: 9}
Ответы
Ответ 1
С Подчеркиванием
Underscore предоставляет функцию _.mapObject
для сопоставления значений и сохранения ключей.
_.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });
// => { one: 3, two: 6, three: 9 }
DEMO
С Lodash
Lodash предоставляет функцию _.mapValues
для сопоставления значений и сохранения ключей.
_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });
// => { one: 3, two: 6, three: 9 }
DEMO
Ответ 2
Мне удалось найти нужную функцию в lodash, библиотеке утилиты, подобной подчеркиванию.
http://lodash.com/docs#mapValues
_.mapValues(object, [callback=identity], [thisArg])
Создает объект с теми же ключами, что и объект, и значения, генерируемые запуская каждое собственное перечислимое свойство объекта посредством обратного вызова. Обратный вызов привязан к thisArg и вызывается с тремя аргументами; (значение, ключ, объект).
Ответ 3
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>
Ответ 4
Я знаю, что это старо, но теперь Underscore имеет новую карту для объектов:
_.mapObject(object, iteratee, [context])
Вы можете, конечно, создать гибкую карту для массивов и объектов
_.fmap = function(arrayOrObject, fn, context){
if(this.isArray(arrayOrObject))
return _.map(arrayOrObject, fn, context);
else
return _.mapObject(arrayOrObject, fn, context);
}
Ответ 5
Как насчет этой версии в простой JS (ES6/ES2015)?
let newObj = Object.assign(...Object.keys(obj).map(k => ({[k]: obj[k] * 3})));
jsbin
Если вы хотите сопоставить объект рекурсивно (на карте вложенной obj), это можно сделать следующим образом:
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
Так как ES7/ES2016 вы можете использовать Object.entries
вместо Object.keys
следующим образом:
let newObj = Object.assign(...Object.entries(obj).map([k, v] => ({[k]: v * 3})));
Ответ 6
_. map возвращает массив, а не объект.
Если вам нужен объект, вам лучше использовать другую функцию, например each
; если вы действительно хотите использовать карту, вы можете сделать что-то вроде этого:
Object.keys(object).map(function(value, index) {
object[value] *= 3;
})
но это сбивает с толку, когда вы видите map
, можно ожидать, что в результате будет получен массив, а затем сделайте что-нибудь с ним.
Ответ 7
Я думаю, вам нужна функция mapValues (чтобы сопоставить функцию над значениями объекта), что достаточно просто реализовать сами:
mapValues = function(obj, f) {
var k, result, v;
result = {};
for (k in obj) {
v = obj[k];
result[k] = f(v);
}
return result;
};
Ответ 8
Я знаю, что это было давно, но все же наиболее очевидное решение с помощью сгиба (иначе сокращение в js) отсутствует, ради полноты я оставлю это здесь:
function mapO(f, o) {
return Object.keys(o).reduce((acc, key) => {
acc[key] = f(o[key])
return acc
}, {})
}
Ответ 9
Исправление смешивания для ошибки отображения подчеркивания: 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;
}
});
Простой обходной путь, который удерживает правый ключ и возвращается как объект
Он по-прежнему используется так же, как и я, вы могли бы использовать эту функцию
для переопределения функции bugy _.map
или просто так, как я использовал его как mixin
_.mapobj ( options , function( val, key, list )
Ответ 10
Вы можете использовать _.mapValues(users, function(o) { return o.age; });
в Lodash и _.mapObject({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });
в Underscore.
Ознакомьтесь с кросс-документацией здесь: http://jonathanpchen.com/underdash-api/#mapvalues-object-iteratee-identity
Ответ 11
const mapObject = (obj = {}, mapper) =>
Object.entries(obj).reduce(
(acc, [key, val]) => ({ ...acc, [key]: mapper(val) }),
{},
);