1507

私はオブジェクトを持っています:

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 に必要なので、クロスブラウザーの問題は気にしません。)

4

39 に答える 39

2168

オブジェクトにネイティブはありませんがmap、これはどうですか?Object

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

Object.keys(myObject).map(function(key, index) {
  myObject[key] *= 2;
});

console.log(myObject);
// => { 'a': 2, 'b': 4, 'c': 6 }

ただし、次を使用してオブジェクトを簡単に反復できますfor ... in

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

for (var key in myObject) {
  if (myObject.hasOwnProperty(key)) {
    myObject[key] *= 2;
  }
}

console.log(myObject);
// { 'a': 2, 'b': 4, 'c': 6 }

アップデート

多くの人が、以前のメソッドは新しいオブジェクトを返すのではなく、オブジェクト自体を操作することに言及しています。さらに言えば、新しいオブジェクトを返し、元のオブジェクトをそのままにしておく別のソリューションを追加したかったのです。

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

// returns a new object with the values at each key mapped using mapFn(value)
function objectMap(object, mapFn) {
  return Object.keys(object).reduce(function(result, key) {
    result[key] = mapFn(object[key])
    return result
  }, {})
}

var newObject = objectMap(myObject, function(value) {
  return value * 2
})

console.log(newObject);
// => { 'a': 2, 'b': 4, 'c': 6 }

console.log(myObject);
// => { 'a': 1, 'b': 2, 'c': 3 }

Array.prototype.reduce前の値を現在の値といくらかマージすることにより、配列を単一の値に減らします。チェーンは空のオブジェクトによって初期化されます{}。反復ごとにmyObject、値の2倍のキーを使用しての新しいキーが追加されます。

アップデート

ES6の新機能により、よりエレガントな表現方法がありobjectMapます。

const objectMap = (obj, fn) =>
  Object.fromEntries(
    Object.entries(obj).map(
      ([k, v], i) => [k, fn(v, k, i)]
    )
  )
  
const myObject = { a: 1, b: 2, c: 3 }

console.log(objectMap(myObject, v => 2 * v)) 

于 2013-02-11T10:52:37.437 に答える
60

書くのはとても簡単です:

Object.map = function(o, f, ctx) {
    ctx = ctx || this;
    var result = {};
    Object.keys(o).forEach(function(k) {
        result[k] = f.call(ctx, o[k], k, o); 
    });
    return result;
}

サンプルコード:

> o = { a: 1, b: 2, c: 3 };
> r = Object.map(o, function(v, k, o) {
     return v * v;
  });
> r
{ a : 1, b: 4, c: 9 }

this注意: このバージョンでは、メソッドと同様に、(オプションで) コールバックのコンテキストを設定することもできますArray

編集- の使用を削除するように変更し、オブジェクトで名前がObject.prototype付けられた既存のプロパティと衝突しないようにしました。map

于 2013-02-11T10:52:20.620 に答える
26

返されたキーの配列を使用Object.keysしてから、次のように操作できます。forEach

var myObject = { 'a': 1, 'b': 2, 'c': 3 },
    newObject = {};
Object.keys(myObject).forEach(function (key) {
    var value = myObject[key];
    newObject[key] = value * value;
});

または、よりモジュール化された方法で:

function map(obj, callback) {
    var result = {};
    Object.keys(obj).forEach(function (key) {
        result[key] = callback.call(obj, obj[key], key, obj);
    });
    return result;
}

newObject = map(myObject, function(x) { return x * x; });

オブジェクト自体の列挙可能なプロパティのみを含む配列を返すため、チェック付きのループObject.keysのように動作することに注意してください。for..inhasOwnProperty

于 2013-02-11T10:53:37.717 に答える
17

オブジェクトを配列にマッピングするための検索と回答を求めてここに来て、結果としてこのページを取得しました。私と同じ答えを探してここに来た場合は、配列にマップしてオブジェクトを作成する方法を次に示します。

次のように map を使用して、オブジェクトから新しい配列を返すことができます。

var newObject = Object.keys(myObject).map(function(key) {
   return myObject[key];
});
于 2015-10-21T17:39:17.123 に答える
8

最高のパフォーマンスのために。

オブジェクトが頻繁に変更されないが、頻繁に反復する必要がある場合は、ネイティブ Map をキャッシュとして使用することをお勧めします。

// example object
var obj = {a: 1, b: 2, c: 'something'};

// caching map
var objMap = new Map(Object.entries(obj));

// fast iteration on Map object
objMap.forEach((item, key) => {
  // do something with an item
  console.log(key, item);
});

Object.entries は、Chrome、Edge、Firefox、およびベータ版の Opera で既に動作するため、将来にわたって保証される機能です。それは ES7 からのものなので、機能しない IE のhttps://github.com/es-shims/Object.entriesをポリフィルします。

于 2016-10-03T10:22:10.237 に答える
7

map functionは存在しませんが、そのようObject.prototypeにエミュレートできます

var myMap = function ( obj, callback ) {

    var result = {};

    for ( var key in obj ) {
        if ( Object.prototype.hasOwnProperty.call( obj, key ) ) {
            if ( typeof callback === 'function' ) {
                result[ key ] = callback.call( obj, obj[ key ], key, obj );
            }
        }
    }

    return result;

};

var myObject = { 'a': 1, 'b': 2, 'c': 3 };

var newObject = myMap( myObject, function ( value, key ) {
    return value * value;
});
于 2013-02-11T10:51:04.640 に答える
6

編集: 新しい JavaScript 機能を使用する標準的な方法は -

const identity = x =>
  x

const omap = (f = identity, o = {}) =>
  Object.fromEntries(
    Object.entries(o).map(([ k, v ]) =>
      [ k, f(v) ]
    )
  )

どこoにオブジェクトfがあり、マッピング関数があります。a -> bまたは、 からの関数と type の値を持つオブジェクトが与えられた場合、 type の値をa持つオブジェクトを生成すると言えますb。疑似型シグネチャとして -

// omap : (a -> b, { a }) -> { b }

mapReduce元の回答は、変換を別の方法で考えることができる強力なコンビネーターを示すために書かれました。

  1. mマッピング関数 – 入力要素を前に変換する機会を与えます…
  2. r縮小関数 - この関数は、アキュムレータをマップされた要素の結果と結合します

直感的に、mapReduce直接プラグインできる新しいレデューサーを作成しArray.prototype.reduceます。omapしかし、もっと重要なことは、オブジェクト モノイドと を利用することで、Object.assignオブジェクトファンクターの実装を単純に実装できること{}です。

const identity = x =>
  x
  
const mapReduce = (m, r) =>
  (a, x) => r (a, m (x))

const omap = (f = identity, o = {}) =>
  Object
    .keys (o)
    .reduce
      ( mapReduce
          ( k => ({ [k]: f (o[k]) })
          , Object.assign
          )
      , {}
      )
          
const square = x =>
  x * x
  
const data =
  { a : 1, b : 2, c : 3 }
  
console .log (omap (square, data))
// { a : 1, b : 4, c : 9 }

私たちが実際に書かなければならなかったプログラムの唯一の部分は、マッピングの実装そのものであることに注意してください –

k => ({ [k]: f (o[k]) })

つまり、既知のオブジェクトoといくつかのキーが与えられた場合k、オブジェクトを構築し、その計算されたプロパティはキーの値kを呼び出した結果です。fo[k]

mapReduce最初に抽象化すると、 の配列決定の可能性を垣間見ることができますoreduce

// oreduce : (string * a -> string * b, b, { a }) -> { b }
const oreduce = (f = identity, r = null, o = {}) =>
  Object
    .keys (o)
    .reduce
      ( mapReduce
          ( k => [ k, o[k] ]
          , f
          )
      , r
      )

// omap : (a -> b, {a}) -> {b}
const omap = (f = identity, o = {}) =>
  oreduce
    ( mapReduce
        ( ([ k, v ]) =>
            ({ [k]: f (v) })
        , Object.assign
        )
    , {}
    , o
    )

すべてが同じように機能しomapますが、より高いレベルで定義できるようになりました。もちろん、新しいObject.entriesことはこれをばかげているように見せますが、演習は学習者にとって依然として重要です。

ここですべての可能性を確認することはできませんがmapReduce、この回答を共有します。これを適用できる場所がいくつあるかを見るのは興味深いからです。それがどのように導出されるか、およびその他の有用な方法に興味がある場合は、この回答を参照してください。

于 2016-08-09T06:12:00.280 に答える
2

私の回答は主に、ここで最も評価の高い回答に基づいています。うまくいけば、誰もが理解してくれます (私の GitHub にも同じ説明があります)。これが、マップを使用した彼の実装が機能する理由です。

Object.keys(images).map((key) => images[key] = 'url(' + '"' + images[key] + '"' +    
')');

この関数の目的は、オブジェクトを取得し、配列を返さずにすべてのオブジェクト (オブジェクトと配列の両方) で使用できるメソッドを使用して、オブジェクトの元の内容を変更することです。JS 内のほとんどすべてがオブジェクトです。そのため、継承のパイプラインのさらに下にある要素は、技術的には、上にある要素が利用できる要素を使用する可能性があります (逆の場合も同様です)。

これが機能する理由は、既存のオブジェクトを単に変更するのではなく、配列の明示的または暗黙的な RETURN を提供する必要がある配列を返す .map 関数によるものです。基本的に、Object.keys を使用してオブジェクトが配列であるとプログラムをだまして、個々のキーが関連付けられている値に作用する map 関数を使用できるようにします (実際には誤って配列を返しましたが、修正しました)。通常の意味での戻りがない限り、元のオブジェクトをそのまま使用して作成され、プログラムどおりに変更された配列はありません。

この特定のプログラムは、images というオブジェクトを取り、そのキーの値を取り、別の関数内で使用するために url タグを追加します。元はこれです:

var images = { 
snow: 'https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305', 
sunny: 'http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-east-   
Matanzas-city- Cuba-20170131-1080.jpg', 
rain: 'https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg' };

...そして変更されたのはこれです:

var images = { 
snow: url('https://www.trbimg.com/img-5aa059f5/turbine/bs-md-weather-20180305'),     
sunny: url('http://www.cubaweather.org/images/weather-photos/large/Sunny-morning-   
east-Matanzas-city- Cuba-20170131-1080.jpg'), 
rain: url('https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg') 
};

オブジェクトの元の構造はそのまま残され、戻り値がない限り、通常のプロパティ アクセスが可能になります。通常のように配列を返さないでください。すべて問題ありません。目標は、元の値 (images[key]) を必要なものに再割り当てすることです。私の知る限り、配列出力を防ぐには、images[key] の REASSIGNMENT が必要であり、配列を返すための暗黙的または明示的な要求は必要ありません (変数の割り当てはこれを行い、私にとっては前後にグリッチしていました)。

編集:

元のオブジェクトの変更を避けるために、新しいオブジェクトの作成に関する彼の他の方法に対処する予定です(出力として誤って配列を作成することを避けるために、再割り当てが必要なようです)。これらの関数は矢印構文を使用し、将来使用するために単に新しいオブジェクトを作成したい場合に使用します。

const mapper = (obj, mapFn) => Object.keys(obj).reduce((result, key) => {
                result[key] = mapFn(obj)[key];
                return result;
            }, {});

var newImages = mapper(images, (value) => value);

これらの関数の仕組みは次のようになります。

mapFn は、後で追加される関数 (この場合 (value) => value) を取り、そこに格納されているものをそのキーの値として単純に返します (または、彼のように戻り値を変更した場合は 2 倍します)。 obj)[キー]、

次に、result[key] = mapFn(obj)[key] でキーに関連付けられた元の値を再定義します。

結果に対して実行された操作を返します (.reduce 関数の最後で開始された括弧内にあるアキュムレータ)。

これはすべて、選択したオブジェクトに対して実行されていますが、返された配列に対する暗黙的な要求はまだありません。私が知る限り、値を再割り当てする場合にのみ機能します。これには多少の頭の体操が必要ですが、上記のように必要なコード行が減ります。出力は、以下に示すものとまったく同じです。

{snow: "https://www.trbimg.com/img-5aa059f5/turbine/bs-   
md-weather-20180305", sunny: "http://www.cubaweather.org/images/weather-
photos/l…morning-east-Matanzas-city-Cuba-20170131-1080.jpg", rain: 
"https://i.pinimg.com/originals/23/d8
/ab/23d8ab1eebc72a123cebc80ce32b43d8.jpg"}

これはNON-NUMBERSで機能することに注意してください。mapFN 関数で値を単純に返すことで、任意のオブジェクトを複製できます。

于 2019-02-06T22:06:06.390 に答える
1

map値だけでなくキーにもpingを実行することに興味がある場合はObject.map(valueMapper, keyMapper)、次のように動作するように書いています。

var source = { a: 1, b: 2 };
function sum(x) { return x + x }

source.map(sum);            // returns { a: 2, b: 4 }
source.map(undefined, sum); // returns { aa: 1, bb: 2 }
source.map(sum, sum);       // returns { aa: 2, bb: 4 }
于 2015-03-16T13:33:26.840 に答える
1

OP が要求したものにより正確に応答するために、OP はオブジェクトを必要とします。

myObject = { 'a': 1, 'b': 2, 'c': 3 }

map メソッドを持つにはmyObject.map

次のように使用される Array.prototype.map に似ています。

newObject = myObject.map(関数 (値, ラベル) {
    戻り値 * 値;
});
// newObject は { 'a': 1, 'b': 4, 'c': 9 } になりました

私見の最良の答え(「尋ねられたものに近い」+「不必要にES {5,6,7}は必要ありません」という観点から測定)の答えは次のとおりです。

myObject.map = function mapForObject(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property) && property != "map"){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

上記のコードは、最近の ECMAScript エディションでのみ利用可能な言語機能を意図的に使用することを避けています。上記のコードを使用すると、次のように問題を解決できます。

myObject = { 'a': 1, 'b': 2, 'c': 3 };

myObject.map = function mapForObject(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property) && property != "map"){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

newObject = myObject.map(function (value, label) {
  return value * value;
});
console.log("newObject is now",newObject);
代替テストコードはこちら

眉をひそめる人もいますが、このようにプロトタイプチェーンにソリューションを挿入する可能性があります.

Object.prototype.map = function(callback)
{
  var result = {};
  for(var property in this){
    if(this.hasOwnProperty(property)){
      result[property] = callback(this[property],property,this);
    }
  }
  return result;
}

注意深い監視の下で行われた場合、悪影響を与えたりmap、他のオブジェクトのメソッドに影響を与えたりしないようにする必要があります(つまり、配列のmap)。

于 2018-12-09T12:44:33.183 に答える
1

まず、Object.entries(collection) を使用して HTMLCollection を変換します。次に、それは iterable であり、.map メソッドを使用できるようになりました。

Object.entries(collection).map(...)

参照 https://medium.com/@js_tut/calling-javascript-code-on-multiple-div-elements-without-the-id-attribute-97ff6a50f31

于 2019-01-09T21:40:22.663 に答える
0

ちょっと役立つかもしれない小さなマッパー関数を書きました。

    function propertyMapper(object, src){
         for (var property in object) {   
           for (var sourceProp in src) {
               if(property === sourceProp){
                 if(Object.prototype.toString.call( property ) === '[object Array]'){
                   propertyMapper(object[property], src[sourceProp]);
                   }else{
                   object[property] = src[sourceProp];
                }
              }
            }
         }
      }
于 2016-01-22T13:55:54.557 に答える
-1

私は特に、単一のオブジェクトの配列に使用していたのと同じ関数を使用したいと考え、それをシンプルに保ちたいと考えていました。これは私のために働いた:

var mapped = [item].map(myMapFunction).pop();
于 2016-10-03T09:20:04.770 に答える
-2
settings = {
  message_notification: {
    value: true,
    is_active: true,
    slug: 'message_notification',
    title: 'Message Notification'
  },
  support_notification: {
    value: true,
    is_active: true,
    slug: 'support_notification',
    title: 'Support Notification'
  },
};

let keys = Object.keys(settings);
keys.map(key=> settings[key].value = false )
console.log(settings)
于 2019-03-01T20:49:55.970 に答える