Показуйте на клавіші збереження об'єктів


129

mapФункція underscore.js, якщо викликається з об'єктом яваскрипт, повертає масив значень , відображених з значень об'єкта.

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

чи є спосіб зберегти ключі? тобто я хочу функцію, яка повертається

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

Якщо ви, як я, завітали сюди, шукаючи функцію "mapValues", яка змінює фактичний об'єкт замість повернення нового, перевірте це просте рішення: stackoverflow.com/questions/30894044/…
Michael Trouw

Відповіді:


228

З підкресленням

Підкреслення забезпечує функцію _.mapObjectвідображення значень та збереження ключів.

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

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

DEMO


З Лодашем

Лодаш надає функцію _.mapValuesдля відображення значень та збереження ключів.

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

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

DEMO


Були докладені зусилля, щоб перетворити функцію _.mapValues ​​на підкреслення: відповідне питання , витягнути запит на _.mapValues . Я сподіваюся, що це пройде :)
raffomania

мені здається, що ти перетворюєш ОБЕКТ в об’єкт, чи я не в думці?
jsh

@jsh У цьому випадку _.map()повертається [['one', 3], ['two', 6], ['three', 9]], що є масивом масивів, і _.object()перетворює його назад в об'єкт.
Єзен Томас

56

Мені вдалося знайти необхідну функцію в lodash, бібліотеці утиліт, подібній до підкреслення.

http://lodash.com/docs#mapValues

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

Створює об'єкт з тими ж ключами, що і об'єкт та значення, згенеровані за допомогою виконання кожного власного перелічуваного властивості об'єкта через зворотний виклик. Зворотний виклик пов'язаний з цимArg і викликається трьома аргументами; (значення, ключ, об’єкт).


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>


13

Я знаю, що це по-старому, але зараз у 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
Примітка для користувачів lodash: jdalton вирішив порушити сумісність з underscore.js через цю зміну. лодаш не підтримає mapObject; дивіться mapValuesзамість методу Лодаша .
Марк Амері

13

Як щодо цієї версії в простому JS ( ES6 / ES2015 )?

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

jsbin

Якщо ви хочете зіставити об'єкт рекурсивно (map вкладений 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})));

5

Я знаю, що минуло давно, але все одно відсутнє найбільш очевидне рішення через fold (він же зменшить js), для повноти я залишу його тут:

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

Я добре з використанням бібліотеки Lodash, але програмісти використовують такі бібліотеки, і не знаючи, як цього можна досягти у ванільній JS. Отже, я ціную вашу відповідь!
cyonder

3

_.map повертає масив, а не об’єкт.

Якщо ви хочете об'єкт, вам краще використовувати іншу функцію, наприклад each; якщо ви дійсно хочете використовувати карту, ви можете зробити щось подібне:

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

але це заплутано, коли побачившись, mapможна було б очікувати, що в результаті з'явиться масив, а потім зробити щось із ним.


У мене було відчуття, читаючи документи, що це було б неприродно, щоб спробувати це в underscore.js. Я думаю, що випадок мого використання є цілком природним, чому вони не підтримують його?
xuanji

Можливо, одна з причин може бути те, що mapвикористовується для зміни входу, що створює масив як вихід, ви можете складати _.objectі _.mapяк @GG. писав, але це питання смаку на даний момент.
Альберто Закканні

3

Я думаю, що вам потрібна функція mapValues (для відображення функції над значеннями об'єкта), яку досить легко реалізувати самостійно:

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


0

Виправлення суміші для підкреслення карти помилки : 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

або просто, як я використовував це як міксин

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.