У меня есть объект:
myObject = { 'a': 1, 'b': 2, 'c': 3 }
Я ищу нативный метод, похожий на Array.prototype.map
тот, который будет использоваться следующим образом:
newObject = myObject.map(function (value, label) {
return value * value;
});
// newObject is now { 'a': 1, 'b': 4, 'c': 9 }
Есть ли в JavaScript такая map
функция для объектов? (Я хочу это для Node.JS, поэтому меня не волнуют кросс-браузерные проблемы.)
javascript
node.js
functional-programming
map-function
Randomblue
источник
источник
Object.keys
, которые не имеют четко определенного порядка. Это может быть проблематично, я предлагаю использоватьObject.getOwnPropertyNames
вместо этого.Object.keys
иObject.getOwnPropertyNames
. См developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...Object.keys
зависит от реализации. См. Stackoverflow.com/a/30919039/1529630Ответы:
Там нет родного
map
дляObject
объекта, но как насчет этого:Но вы можете легко перебрать объект, используя
for ... in
:Обновить
Многие люди упоминают, что предыдущие методы не возвращают новый объект, а работают с самим объектом. В связи с этим я хотел добавить другое решение, которое возвращает новый объект и оставляет исходный объект как есть:
Array.prototype.reduce
уменьшает массив до единственного значения путем некоторого слияния предыдущего значения с текущим. Цепочка инициализируется пустым объектом{}
. На каждой итерацииmyObject
добавляется новый ключ с двойным ключом в качестве значения.Обновить
С новыми функциями ES6, есть более элегантный способ выразить
objectMap
.источник
map
правильно, потому что он не делаетreturn
- он злоупотребляет,map
как если бы это былforEach
вызов. Если бы он действительно это сделал,return myObject[value] * 2
то результатом был бы массив, содержащий удвоенные исходные значения, вместо объекта, содержащего исходные ключи с удвоенными значениями, причем последний явно соответствует тому, что запрашивал OP..reduce
пример в порядке, но, по- моему , он по-прежнему далеко не удобен.map
для объектов, поскольку.reduce
обратный вызов не только должен соответствовать способу.reduce
работы, но также требует, чтобы онmyObject
был доступен в лексической области видимости. Последнее, в частности, делает невозможным просто передать ссылку на функцию в обратном вызове, требуя вместо этого анонимную функцию на месте..map
это неподходящий метод для использования, когда вы не собираетесь использовать результирующий отображенный массив - если вы хотите использовать только побочные эффекты, такие как в вашем первом коде, вы должны определенно использоватьforEach
вместо этого.Как насчет одного вкладыша с немедленным назначением переменной в простом JS ( ES6 / ES2015 )?
Использование оператора распространения и синтаксиса имени вычисляемого ключа :
jsbin
Другая версия, использующая Reduce:
jsbin
Первый пример как функция:
jsbin
Если вы хотите отобразить вложенный объект рекурсивно в функциональном стиле, это можно сделать так:
jsbin
Или более обязательно, как это:
jsbin
Начиная с ES7 / ES2016 вы можете использовать
Object.entries()
вместо,Object.keys()
например, так:ES2019 представил
Object.fromEntries()
, что упрощает это еще больше:Унаследованные свойства и прототип цепочки:
В некоторых редких случаях вам может понадобиться отобразить объект класса, который содержит свойства унаследованного объекта в его цепочке прототипов . В таких случаях
Object.keys()
не будет работать, потомуObject.keys()
что не перечисляет унаследованные свойства. Если вам нужно отобразить унаследованные свойства, вы должны использоватьfor (key in myObj) {...}
.Вот пример объекта, который наследует свойства другого объекта и как
Object.keys()
не работает в таком сценарии.jsbin
Однако, пожалуйста, сделайте мне одолжение и избегайте наследства . :-)
источник
Object.keys
не перечисляются унаследованные свойства. Я предлагаю вам добавить предупреждение.Object.entries({a: 1, b: 2, c: 3})
.(o, f)
аргументами, но употребляете ихobj
в теле.Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
не работает, еслиobj
это пустой объект. Изменить на:Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))
.Нет нативных методов, но lodash # mapValues отлично справится с этой задачей.
источник
Object.entries({a: 1, b: 2, c: 3})
чтобы получить массив._.map()
чтобы получить ключ в качестве второго аргумента - как того требует OP._.mapValues()
также предоставляет ключ в качестве второго аргумента. Также_.map()
не будет работать здесь, поскольку он возвращает только массивы, а не объекты:_.map({ 'a': 1, 'b': 2, 'c': 3}, n => n * 3) // [3, 6, 9]
Это довольно легко написать:
с примером кода:
NB: эта версия также позволяет вам (опционально) устанавливать
this
контекст для обратного вызова, как иArray
метод.РЕДАКТИРОВАТЬ - изменено, чтобы удалить использование
Object.prototype
, чтобы оно не конфликтовало с каким-либо существующим свойством, названнымmap
в объекте.источник
map
, но я должен сказать, что изменениеObject.prototype
меня не устраивает, даже если оно не перечисляемо.Object.prototype
кроме (теоретического) риска столкновения с другими методами. FWIW, я не могу понять, как другой ответ получил столько же голосов, сколько он имеет, это совершенно неправильно.o = {map: true, image: false}
. Вы рискуете просто написатьo.map(fn)
вместоmap(o,fn)
Вы можете использовать
Object.keys
и затемforEach
возвращенный массив ключей:Или более модульным способом:
Обратите внимание, что
Object.keys
возвращает массив, содержащий только собственные перечисляемые свойства объекта, поэтому он ведет себя какfor..in
цикл сhasOwnProperty
проверкой.источник
Это прям бразильцы, и все в сообществе JS знают это. Там должна быть такая функциональность:
вот наивная реализация:
Это очень раздражает, когда приходится все время реализовывать самостоятельно;)
Если вы хотите что-то более сложное, которое не мешает классу Object, попробуйте это:
но безопасно добавить эту функцию карты в Object, просто не добавляйте в Object.prototype.
источник
Object
объект? Просто естьconst mapObject = (obj, fn) => { [...]; return ret; }
..map
обычно понимается как интерфейс Functor, и не существует единого определения Functor для «Объекта», потому что практически все в javascript может быть объектом, включая вещи со своими собственными очень четкими и определенными интерфейсами / логикой .map.Я пришел сюда, чтобы найти и ответить для отображения объекта в массив, и в результате получил эту страницу. В случае, если вы пришли сюда в поисках того же ответа, что и я, вот как вы можете сопоставить массив и объект.
Вы можете использовать map для возврата нового массива из объекта следующим образом:
источник
Object.values(myObject)
Принятый ответ имеет два недостатка:
Array.prototype.reduce
, потому что сокращение означает изменение структуры составного типа, чего не происходит в этом случае.Функциональный подход ES6 / ES2015
Обратите внимание, что все функции определены в карри.
o
переназначается. Поскольку Javascript передает ссылочные значения путем совместного использования , создается неглубокая копияo
. Теперь мы можем мутироватьo
внутриomap
без мутацииo
в родительской области видимости.map
возвращаемое значение игнорируется, посколькуmap
выполняет мутациюo
. Поскольку этот побочный эффект остается внутриomap
и не виден в родительской области, он полностью приемлем.Это не самое быстрое решение, но декларативное и многоразовое. Вот та же реализация, что и в одной строке, краткая, но менее читаемая:
Приложение - почему объекты не повторяются по умолчанию?
ES2015 определяет итератор и итерируемые протоколы. Но объекты все еще не повторяемы и, следовательно, не отображаются. Причина заключается в смешении данных и уровня программы .
источник
Array.prototype.reduce
. Все, что я хочу проиллюстрировать здесь, это то, что принятый ответ как-то «злоупотребляет»Array.prototype.reduce
и как может быть реализовано чисто функциональное отображение. Если вас не интересует функциональное программирование, просто проигнорируйте мой ответ.fold
является более общим, чемmap
(функтор). Тем не менее, это были мои знания с середины 2016 года. Это пол вечности: DJavaScript только что получил новый
Object.fromEntries
метод.пример
объяснение
Приведенный выше код преобразует объект во вложенный массив (
[[<key>,<value>], ...]
), который можно отобразить.Object.fromEntries
преобразует массив обратно в объект.Крутая вещь в этом шаблоне заключается в том, что теперь вы можете легко учитывать ключи объектов при отображении.
Документация
Object.fromEntries()
Object.entries()
Поддержка браузера
Object.fromEntries
в настоящее время поддерживается только этими браузерами / движками , тем не менее, есть доступные полифилы (например, @ babel / polyfill ).источник
Object.fromEntries
это противоположностьObject.entries
.Object.entries
преобразует объект в список пар ключ-значение.Object.fromEntries
преобразует список пар ключ-значение в объект.Минимальная версия (es6):
источник
Object.entries(obj).reduce((a, [k, v]) => [a[k] = v * v, a], {})
, угловые скобки вместо скобок.Object.entries(obj).reduce((a, [k, v]) => {a[k] = v * v; return a}, {})
Object.entries().reduce
это лучшее решение , которое я думаю , что с ES6 + .Would получить больше upvotes , если он использовалreturn
заявление в редукторе , а неimplicit return
иcomma
оператора - что аккуратный , но трудно читать ИМХОДля максимальной производительности.
Если ваш объект не меняется часто, но его нужно часто повторять, я предлагаю использовать собственную карту в качестве кэша.
Object.entries уже работает в Chrome, Edge, Firefox и бета-версии Opera, поэтому эта функция ориентирована на будущее. Он из ES7, поэтому заполняйте его https://github.com/es-shims/Object.entries для IE, где он не работает.
источник
const fn = v => v * 2; const newObj = Object.entries(myObject).reduce((acc, [k,v]) => Object.assign({}, acc, {[k]: fn(v)}), {});
Вы можете использовать
map
метод иforEach
на массивах, но если вы хотите использовать его наObject
тогда, вы можете использовать его с поворотом, как показано ниже:Использование Javascript (ES6)
Использование jQuery
Или вы можете использовать другие циклы также как
$.each
метод, как показано ниже:источник
$
jquery?map function
Не существует наObject.prototype
однако вы можете подражать ему , как такисточник
typeof callback === 'function'
абсолютно излишни. 1)map
не имеет смысла без обратного вызова 2) еслиcallback
не функция, вашаmap
реализация просто выполняет бессмысленный цикл for. Кроме того,Object.prototype.hasOwnProperty.call( obj, key )
это немного излишне.Я натолкнулся на это как на первый элемент в поиске Google, пытаясь научиться делать это, и подумал, что поделюсь с другими людьми, которые недавно нашли это решение, которое я нашел, использующее неизменяемый пакет npm.
Я думаю, что им интересно поделиться, потому что immutable использует ситуацию EXACT OP в своей собственной документации - ниже не мой собственный код, а взятый из текущей документации immutable-js:
Не то, чтобы у Seq были другие свойства («Seq описывает ленивую операцию, позволяющую им эффективно объединять в цепочку все методы сбора данных более высокого порядка (такие как map и filter), не создавая промежуточные коллекции»), и что некоторые другие данные immutable-js Структуры также могут выполнять работу достаточно эффективно.
Любой, кто использует этот метод, конечно, должен
npm install immutable
и может захотеть прочитать документы:https://facebook.github.io/immutable-js/
источник
РЕДАКТИРОВАТЬ: канонический способ использования новых функций JavaScript это -
Где
o
какой-то объект иf
ваша функция отображения. Или мы можем сказать, что, учитывая функцию froma -> b
и объект со значениями типаa
, создаем объект со значениями типаb
. Как подпись псевдо-типа -Оригинальный ответ был написан, чтобы продемонстрировать мощный комбинатор,
mapReduce
который позволяет нам думать о нашем преобразовании по-другомуm
, отображение функция - дает вам возможность преобразовать входящий элемент до того, как…r
, То сокращение функция - это функция , сочетает в себе аккумулятор с результатом отображенного элементаИнтуитивно понятно,
mapReduce
создает новый редуктор, к которому мы можем подключиться напрямуюArray.prototype.reduce
. Но что еще более важно, мы можем реализовать нашу реализацию объектного функтораomap
просто, используя объект monoid,Object.assign
и{}
.Обратите внимание, что единственная часть программы, которую мы фактически должны были написать, - это сама реализация отображения.
Что говорит, учитывая известный объект
o
и некоторый ключk
, создает объект, и его вычисленное свойствоk
является результатом вызоваf
значения ключа,o[k]
.Мы получим представление о
mapReduce
потенциале секвенирования, если сначала рассмотримoreduce
Все работает одинаково, но
omap
теперь может быть определено на более высоком уровне. Конечно новыйObject.entries
это выглядит глупо, но упражнение все еще важно для ученика.Вы не увидите весь потенциал
mapReduce
здесь, но я поделюсь этим ответом, потому что интересно посмотреть, сколько мест его можно применить. Если вы заинтересованы в том, как это происходит и как это может быть полезно, пожалуйста, посмотрите этот ответ .источник
Map
иMap.entries
окей: D. Я устал от использования простых объектов в качестве типов картографических данных.Map
следует использовать там, где это возможно, когда это возможно, но это не полностью заменяет необходимость использования этих процедур на простых объектах JS, хотя: DОсновываясь на ответе @Amberlamps, вот полезная функция (как комментарий это выглядело некрасиво)
и использование это:
источник
источник
enumerable
по умолчаниюfalse
Мой ответ в значительной степени основан на ответе с самым высоким рейтингом, и, надеюсь, все это понимают (тоже самое объяснение на моем GitHub). Вот почему его имплементация с картой работает:
Назначение функции - взять объект и изменить исходное содержимое объекта, используя метод, доступный для всех объектов (как объектов, так и массивов) без возврата массива. Почти все в JS является объектом, и по этой причине элементы, расположенные ниже по конвейеру наследования, могут технически использовать те, которые доступны для тех, кто находится на линии вверх (и наоборот).
Причина этого заключается в том, что функции .map возвращают массив, ТРЕБУЮЩИЙ, что вы предоставляете явный или неявный ВОЗВРАТ массива вместо простой модификации существующего объекта. По сути, вы заставляете программу думать, что объект является массивом, используя Object.keys, который позволит вам использовать функцию map, воздействуя на значения, с которыми связаны отдельные ключи (я фактически случайно возвратил массивы, но исправил это). Пока нет возврата в обычном смысле, не будет никакого массива, созданного с оригинальным объектом, все еще целым и измененным как запрограммированный.
Эта конкретная программа принимает объект с именем images, принимает значения его ключей и добавляет URL-теги для использования в другой функции. Оригинал это:
... и модифицировано это:
Первоначальная структура объекта остается неизменной, что обеспечивает нормальный доступ к свойству, если нет возврата. НЕ возвращайте массив, как обычно, и все будет хорошо. Цель - переназначить исходные значения (изображения [ключ]) на то, что нужно, а не на что-либо еще. Насколько я знаю, для предотвращения вывода массива ДОЛЖНА быть ПЕРЕОБРАЗОВАНИЕ изображений [ключ] и неявный или неявный запрос на возврат массива (назначение переменных делает это и дает сбой мне и обратно).
РЕДАКТИРОВАТЬ:
Собираюсь обратиться к своему другому методу относительно создания нового объекта, чтобы избежать изменения исходного объекта (и переназначение, по-видимому, все еще необходимо, чтобы избежать случайного создания массива в качестве вывода). Эти функции используют синтаксис стрелки и, если вы просто хотите создать новый объект для будущего использования.
Принцип работы этих функций выглядит следующим образом:
mapFn берет функцию, которая будет добавлена позже (в этом случае (value) => value), и просто возвращает все, что там хранится, в качестве значения для этого ключа (или умножается на два, если вы измените возвращаемое значение, как он сделал) в mapFn ( объект) [ключ],
а затем переопределяет исходное значение, связанное с ключом, в результате [ключ] = mapFn (obj) [ключ]
и возвращает операцию, выполненную с результатом (аккумулятор, расположенный в скобках, инициированный в конце функции .reduce).
Все это выполняется на выбранном объекте, и ЕЩЕ НЕ МОЖЕТ быть неявный запрос возвращаемого массива, и он работает только при переназначении значений, насколько я могу судить. Это требует некоторой умственной гимнастики, но сокращает количество необходимых строк кода, как видно выше. Вывод точно такой же, как видно ниже:
Имейте в виду, что это работает с NUMNUMERS. Вы МОЖЕТЕ Дублировать ЛЮБОЙ объект, ПРОСТО ВОЗВРАЩАЯ ЗНАЧЕНИЕ в функции mapFN.
источник
Первая функция отвечает на вопрос. Создает карту.
Вторая функция не создает карту. Вместо этого он просматривает свойства в существующем объекте используя
hasOwnProperty()
. Эта альтернатива карты может быть лучшим решением в некоторых ситуациях.источник
Если вы заинтересованы в
map
пинге не только значений, но и ключей, я написалObject.map(valueMapper, keyMapper)
, что ведет себя так:источник
npm install @mattisg/object.map
.Мне нужна была версия, которая также позволяла изменять ключи (на основе ответов @Amberlamps и @yonatanmn);
factObject =
Редактировать: небольшое изменение для передачи в начальный объект {}. Позволяет ему быть [] (если ключи целые)
источник
Я специально хотел использовать ту же функцию, что и для массивов для одного объекта, и хотел, чтобы она была простой. Это сработало для меня:
источник
var mapped = myMapFunction(item)
Чтобы более точно реагировать на то, что именно запрашивал ОП, ОП хочет объект:
иметь метод карты
myObject.map
,Имхо лучше (измеряется в терминах к « близко к тому , что просят » + «не требуется ES {5,6,7} без необходимости») ответ был бы:
Приведенный выше код избегает преднамеренного использования каких-либо языковых функций, доступных только в последних выпусках ECMAScript. С помощью кода выше проблема может быть решена следующим образом:
Помимо того, что некоторые нахмурились, была бы возможность вставить решение в цепочку прототипов следующим образом.
Что-то, что при тщательном надзоре не должно иметь каких-либо побочных эффектов и не влиять на
map
методы других объектов (например, массивовmap
).источник
Сначала преобразуйте свою коллекцию HTMLCollection с помощью Object.entries (collection). Тогда это итеративно, теперь вы можете использовать метод .map для него.
ссылка https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31
источник
Определить функцию mapEntries.
mapEntries принимает функцию обратного вызова, которая вызывается для каждой записи в объекте со значением параметра, ключом и объектом. Он должен вернуть новое значение.
mapEntries должен вернуть новый объект с новыми значениями, возвращенными из обратного вызова.
Редактировать: в предыдущей версии не указывалось, что это не перечисляемое свойство
источник
Эй, написал небольшую картографическую функцию, которая может помочь.
источник
Другой подход заключается в использовании пользовательской функции json stringify, которая также может работать с глубокими объектами. Это может быть полезно, если вы собираетесь отправить его на сервер в любом случае как json
источник
Я работаю только со строками, чтобы уменьшить количество исключений:
источник
Object Mapper в TypeScript
Мне нравятся примеры, которые используют,
Object.fromEntries
такие как этот , но тем не менее, они не очень просты в использовании. Ответы, которые используют,Object.keys
а затем ищут, наkey
самом деле делают несколько поисков, которые могут не понадобиться.Хотелось бы, чтобы была
Object.map
функция, но мы можем создать свою собственную и вызывать ееobjectMap
с возможностью изменятьkey
иvalue
:Использование (JavaScript):
Код (TypeScript):
Если вы не используете TypeScript, скопируйте приведенный выше код в TypeScript Playground, чтобы получить код JavaScript.
Кроме того , почему я поставил
keySelector
после того, какvalSelector
в списке параметров, потому , что это не является обязательным.* Некоторые кредиты идут на ответ Александра Миллса .
источник
Эта функция рекурсивно проходит через объект и массивы объектов. Атрибуты могут быть удалены, если они возвращены неопределенными
источник