nesneler için harita işlevi (diziler yerine)


1065

Bir nesnem var:

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

Ben yerel bir yöntem, buna benzer Array.prototype.mapaşağıdaki gibi arıyorum :

newObject = myObject.map(function (value, label) {
    return value * value;
});

// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

JavaScript'in mapnesneler için böyle bir işlevi var mı ? (Bunu Node.JS için istiyorum, bu yüzden tarayıcılar arası sorunları umursamıyorum.)


1
Çoğu cevap Object.keys, iyi tanımlanmış bir sıraya sahip değildir. Bu sorunlu olabilir, Object.getOwnPropertyNamesbunun yerine kullanmanızı öneririm .
Oriol

14
JS'nin bu inanılmaz ilkel görevi sağlamadığı için inanılmaz.
jchook

3
@Oriol bundan emin misin? MDN web Docs göre dizi öğelerinin sipariş arasındaki tutarlı Object.keysve Object.getOwnPropertyNames. Bkz. Developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
Bart

@Bart Sırası Object.keysuygulamaya bağlıdır. Bkz. Stackoverflow.com/a/30919039/1529630
Oriol

4
@Oriol Zaten nesnelerdeki anahtarların sırasına güvenmemelisiniz, bu yüzden soru ile ilgisi yoktur - çünkü siparişin onun için önemli olduğunu asla belirtmedi. Ve eğer düzen onun için önemliyse, hiçbir şekilde bir nesne kullanmamalıydı.
BT

Yanıtlar:


1541

Hiçbir yerli mapiçin Objectnesne, ancak buna ne dersin:

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 }

Ancak aşağıdakileri kullanarak kolayca bir nesne üzerinde yineleme yapabilirsiniz 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 }

Güncelleme

Birçok insan önceki yöntemlerin yeni bir nesne döndürmediğini, aksine nesnenin kendisi üzerinde çalıştığını belirtiyor. Bu nedenle yeni bir nesne döndüren ve orijinal nesneyi olduğu gibi bırakan başka bir çözüm eklemek istedim:

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önceki değeri akımla bir araya getirerek bir diziyi tek bir değere düşürür. Zincir boş bir nesne tarafından başlatılır {}. Her yinelemeye myObject, değerin iki katı olan yeni bir anahtar eklenir.

Güncelleme

Yeni ES6 özellikleri ile ifade etmenin daha zarif bir yolu var 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)) 


3
Evet, bu tür bir sorun için çözümümü tavsiye etmem. Bu yüzden cevabımı alternatif, daha iyi bir çözümle güncelledim.
Amberlamps

1
Cevabımı güncelledim - görünüşe göre (soruyu yeniden okurken) OP , aynı anahtarlara sahip yeni bir nesne istiyor , değerlerin sağlanan işlevle mutasyona uğradığı ve orijinal nesneyi yerinde değiştirmek için değil.
Alnitak

13
@KhalilRavanna Bence burada kodu yanlış okudum - bu cevap mapdoğru kullanmıyor çünkü yapmıyor çünkü return- mapsanki bir forEachçağrı sanki kötüye . Eğer gerçekten yapsaydı return myObject[value] * 2 , sonuç , iki kat değerli değerlere sahip orijinal anahtarları içeren bir nesne yerine, iki katına çıkmış orijinal değerleri içeren bir dizi olurdu , ikincisi OP'nin istediği şeydir.
Alnitak

3
@Amberlamps .reduceörneğiniz tamam, ancak IMHO hala a .mapObjects için kolaylıktan çok daha uzun bir süre düşüyor , çünkü .reducegeri aramanız sadece .reduceçalışma yöntemiyle eşleşmek zorunda değil , aynı zamanda myObjectsözlüksel kapsamda mevcut olmasını da gerektiriyor . İkincisi, geri aramada bir işlev referansını iletmeyi imkansız hale getirir, bunun yerine yerinde anonim bir işlev gerektirir.
Alnitak

8
TBH Bu cevapta sunulan ikinci çözümü sadece (ya da başlangıçta) sağlayan bir cevabı iptal etmiş olmayı tercih ederim. Birincisi işe yarıyor ve mutlaka yanlış değil, ancak diğerlerinin de belirttiği gibi, haritanın bu şekilde kullanıldığını görmek istemiyorum. Haritayı gördüğümde, zihnim otomatik olarak "değişmez veri yapısı" düşünüyor
mjohnsonengr

308

Düz JS'de ( ES6 / ES2015 ) hemen değişken atamasına sahip bir astar nasıl olur ?

Forma operatörünü ve hesaplanan anahtar adı sözdizimini kullanma:

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

jsbin

Reduce kullanan başka bir sürüm:

let newObj = Object.keys(obj).reduce((p, c) => ({...p, [c]: obj[c] * obj[c]}), {});

jsbin

İşlev olarak ilk örnek:

const oMap = (o, f) => Object.assign({}, ...Object.keys(o).map(k => ({ [k]: f(o[k]) })));

// To square each value you can call it like this:
let mappedObj = oMap(myObj, (x) => x * x);

jsbin

Eğer iç içe bir nesneyi eşleştirmek istiyorsanız yinelemeli bir de fonksiyonel bir tarzda, bu gibi yapılabilir:

const sqrObjRecursive = obj =>
  Object.keys(obj).reduce(
    (newObj, key) =>
      obj[key] && typeof obj[key] === "object"
        ? { ...newObj, [key]: sqrObjRecursive(obj[key]) } // recurse.
        : { ...newObj, [key]: obj[key] * obj[key] }, // square val.
    {}
  );       

jsbin

Veya daha zorunlu olarak, şöyle:

const sqrObjRecursive = obj => {
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === "object") obj[key] = sqrObjRecursive(obj[key]);
    else obj[key] = obj[key] * obj[key];
  });
  return obj;
};

jsbin

ES7 / ES2016'dan bu yana Object.entries(), Object.keys()örneğin bunun yerine kullanabilirsiniz :

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

BunuObject.fromEntries() daha da basitleştiren ES2019 tanıtıldı :

let newObj = Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, v * v]));


Kalıtsal özellikler ve prototip zinciri:

Bazı nadir durumlarda , miras alınan bir nesnenin özelliklerini prototip zincirinde tutan sınıfa benzer bir nesneyi eşlemeniz gerekebilir . Bu gibi durumlarda işe yaramaz, çünkü miras alınan mülkleri numaralandırmaz . Devralınan özellikleri eşlemeniz gerekiyorsa , kullanmalısınız .Object.keys()Object.keys()for (key in myObj) {...}

Aşağıda, başka bir nesnenin özelliklerini devralan ve Object.keys()bu senaryoda nasıl çalışmayan bir nesneye örnek verilmiştir .

const obj1 = { 'a': 1, 'b': 2, 'c': 3}
const obj2 = Object.create(obj1);  // One of multiple ways to inherit an object in JS.

// Here you see how the properties of obj1 sit on the 'prototype' of obj2
console.log(obj2)  // Prints: obj2.__proto__ = { 'a': 1, 'b': 2, 'c': 3}

console.log(Object.keys(obj2));  // Prints: an empty Array.

for (key in obj2) {
  console.log(key);              // Prints: 'a', 'b', 'c'
}

jsbin

Ancak, lütfen bana bir iyilik yapın ve kalıtımdan kaçının . :-)


1
Güzel ama Object.keyskalıtsal mülkleri numaralandırmadığı gerçeğine yakalandım . Bir uyarı eklemenizi öneririm.
David Braun

Cevabınızı kısaltmak için kullanın Object.entries({a: 1, b: 2, c: 3}).

1
Bazı yazım hatalarınız var ( (o, f)argümanlar olarak obj
bahsediyorsunuz

4
Evet ve sonra bir sonraki kişinin bu işlevin ne olduğunu anlamaya birkaç dakika ayırmasına izin verin? :)
Andrey Popov

1
Boş bir nesne Object.assign(...Object.entries(obj).map(([k, v]) => ({[k]: v * v})))ise çözüm çalışmaz obj. Değiştirin: Object.assign({}, ...Object.entries(obj).map(([k, v]) => ({[k]: v * v}))).
blackcatweb

115

Yerel yöntem yok, ancak lodash # mapValues işi mükemmel bir şekilde yapacak

_.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
// → { 'a': 3, 'b': 6, 'c': 9 }

6
Yalnızca bir işlev için fazladan bir HTTP çağrısı ve fazladan bir kitaplık eklemenize gerek yoktur. Her durumda, bu cevap şimdi modası geçmiş ve sadece Object.entries({a: 1, b: 2, c: 3})bir dizi almak için arayabilirsiniz .

11
Bir diziyi almak neden yararlıdır? Bu gereksinim eşlenen bir nesne içindi. Ayrıca, ES6'nın yardımcı program kitaplıklarını son zamanlarda bir dereceye kadar kullanma zorunluluğunu engellediği oldukça az şey olmasına rağmen, bu tür bir şey için temel olarak inşa edilmiş popüler bir kütüphane olan Lodash'ı kullanmak için ima edilen bir HTTP çağrısı yoktur.
corse32

2
Lodash çekmek için ekstra HTTP çağrısı sanırım. Bu sizin tek kullanım durumunuzsa, aslında aşırıya kaçmaktır. Yine de, Lodash'ın bu kadar yaygın bir kütüphane olması için bu cevabın olması mantıklı.
igorsantos07

2
bahsetmemeniz için kullanmanız _.map()gerekir, böylece OP'nin gerektirdiği şekilde anahtarı ikinci argüman olarak alırsınız.
igorsantos07

_.mapValues()anahtarı ikinci argüman olarak da sağlar. Ayrıca _.map()burada değil, sadece dizileri döndürür, çünkü nesneleri _.map({ 'a': 1, 'b': 2, 'c': 3}, n => n * 3) // [3, 6, 9]
işe yaramaz

57

Birini yazmak oldukça kolay:

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;
}

örnek kod ile:

> 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 }

Not: Bu sürüm aynı zamanda (isteğe bağlı olarak) yöntem thisgibi, geri arama için bağlam ayarlamanıza da olanak tanır Array.

EDIT - nesnenin üzerinde Object.prototypevar olan herhangi bir özellikle çakışmamasını sağlamak için, kullanımını kaldırmak üzere değiştirildi map.


3
Tamam. :) Bu soru üzerine bir yorum beni buraya getirdi. Kabul edilen cevap açıkça kötüye kullanıldığından bunu + 1'leyeceğim map, ancak değiştirmenin Object.prototypenumaralandırılmasa bile benimle iyi oturmadığını söylemeliyim .
JLRishe

2
@JLRishe Teşekkürler. ES5'te IMHO'nun (teorik) çarpışma riskini başka yöntemlerle değiştirmekten başka bir neden kalmadıObject.prototype . FWIW, diğer cevabın sahip olduğu kadar oy aldığını anlayamıyorum, tamamen yanlış.
Alnitak

7
@JLR Eski bir moruk olduğunuzu anlayın ... zamanları alın ve bu prototipi değiştirin!
Nick Manning

12
@NickManning Genç kırbaçlananlar ve sorumsuz davranışlarınız. Bahçemden çık!
JLRishe

3
Bu zaten çalışmıyor: o = {map: true, image: false}. Sen ediyoruz bunu riske sadece yazmak için o.map(fn)yerinemap(o,fn)
fregante

25

Object.keysVe sonra forEachdöndürülen anahtar dizisini kullanabilirsiniz :

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

Veya daha modüler bir şekilde:

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.keysYalnızca nesnenin kendi numaralandırılabilir özelliklerini içeren bir dizi döndürdüğünü unutmayın , bu nedenle çek for..iniçeren bir döngü gibi davranır hasOwnProperty.


20

Bu düz bs ve JS topluluğundaki herkes bunu biliyor. Orada gereken bu işlev be:

const obj1 = {a:4, b:7};
const obj2 = Object.map(obj1, (k,v) => v + 5);

console.log(obj1); // {a:4, b:7}
console.log(obj2); // {a:9, b:12}

İşte naif uygulama:

Object.map = function(obj, fn, ctx){

    const ret = {};

    for(let k of Object.keys(obj)){
        ret[k] = fn.call(ctx || null, k, obj[k]);
    });

    return ret;
};

Bunu her zaman kendiniz uygulamak çok can sıkıcıdır;)

Biraz daha karmaşık bir şey istiyorsanız, bu Object sınıfını engellemezse şunu deneyin:

let map = function (obj, fn, ctx) {
  return Object.keys(obj).reduce((a, b) => {
    a[b] = fn.call(ctx || null, b, obj[b]);
    return a;
  }, {});
};


const x = map({a: 2, b: 4}, (k,v) => {
    return v*2;
});

ancak bu harita işlevini Object'e eklemek güvenlidir, Object.prototype'e eklemeyin.

Object.map = ... // fairly safe
Object.prototype.map ... // not ok

Neden bu işlevi genel Objectnesneye ekliyorsunuz ? Sadece var const mapObject = (obj, fn) => { [...]; return ret; }.
Amberlamps

7
O :) Nesne üzerinde bir yöntem olmalıdır Çünkü
Alexander Mills

1
Object.prototype ile uğraşmadığımız sürece iyi olmalıyız
Alexander Mills

1
Harita sadece rastgele belirsiz bir şey olsaydı, elbette. Ancak .mapgenellikle bir Functor arabirimi olarak anlaşılır ve Functor'un "Object" için tek bir tanımı yoktur, çünkü javascript'teki hemen hemen her şey kendi çok farklı ve tanımlanmış .map arabirimleri / mantığı olan şeyleri içeren bir Object olabilir.
Dtipson

1
Kanımca, geri arama ilk argümanı bir anahtar değil, yinelenen öğenin kendisi olmalıdır. Örneğin, her zamanki gibi ortak harita ile olduğu gibi bana aynı nesneyi vermesi gerektiğini varsayalım: Object.map ({prop: 1}, el => el) ama aynı anahtar adı değerine sahip anahtarlar döndürüyor ...
Gleb Dolzikov

17

Buraya bir nesneyi bir diziye eşlemek ve bulmak için geldim ve sonuç olarak bu sayfayı aldım. Buraya benimle aynı cevabı aramaya geldiysen, bir diziyi nasıl eşleyip nesne oluşturabileceğin budur.

Nesneden aşağıdaki gibi yeni bir dizi döndürmek için haritayı kullanabilirsiniz:

var newObject = Object.keys(myObject).map(function(key) {
   return myObject[key];
});

6
Bu uzaktan çalışmaz - sadece nesnenin değerlerinin bir dizisini döndürür, yeni bir nesne değil. Bu kadar oyu olduğuna inanamıyorum.
Alnitak

1
Haklısınız, bir nesneyi ve nesneyi eşlemek için bir cevap ararken soruyu doğru cevaplamıyor. Buraya bir nesneyi bir diziye eşlemek için bir cevap aramaya geldim ve sonuç olarak bu sayfayı aldım, bu yüzden cevabımı bırakacağım ve bunun sonucu olarak buraya gelmiş olabilecek insanlar için alternatif bir cevap olduğunu yansıtacak şekilde düzenleyeceğim. bir nesneyi dizilerle eşlemek için.
JoeTron

5
ES7'de bu önemsiz bir şekilde olacakObject.values(myObject)
Alnitak

1
Bunu bilmek güzel, ancak bazı insanlar hala eski kodu kullanmak zorunda.
JoeTron

const obj = {foo: 'bar', baz: 42}; console.log (Object.entries (obj)); // [['foo', 'bar'], ['baz', 42]]
Bashirpour

12

Kabul edilen cevabın iki dezavantajı vardır:

  • Yanlış kullanır Array.prototype.reduce, çünkü bu durumda olmayan bir kompozit tipin yapısını değiştirmek için azaltma araçları.
  • Özellikle tekrar kullanılamaz

ES6 / ES2015 fonksiyonel yaklaşımı

Lütfen tüm fonksiyonların kıvrımlı biçimde tanımlandığını unutmayın.

// small, reusable auxiliary functions

const keys = o => Object.keys(o);

const assign = (...o) => Object.assign({}, ...o);

const map = f => xs => xs.map(x => f(x));

const mul = y => x => x * y;

const sqr = x => mul(x) (x);


// the actual map function

const omap = f => o => {
  o = assign(o); // A
  map(x => o[x] = f(o[x])) (keys(o)); // B
  return o;
};


// mock data

const o = {"a":1, "b":2, "c":3};


// and run

console.log(omap(sqr) (o));
console.log(omap(mul(10)) (o));

  • A satırında oyeniden atanır. Javascript referans değerlerini paylaşarak geçtiğinden , sığ bir kopyası ooluşturulur. Artık mutasyona uğramadan oiçinde omapmutasyona geçebiliyoruzo ana kapsamda .
  • B satırında mapdönüş değeri yok sayılır, çünkü mapbir mutasyon gerçekleştirir o. Bu yan etki içeride kaldığı omapve ana kapsamda görünmediği için tamamen kabul edilebilir.

Bu en hızlı çözüm değil, deklaratif ve tekrar kullanılabilir bir çözümdür. İşte tek satırlık, özlü ama daha az okunabilir olanla aynı uygulama:

const omap = f => o => (o = assign(o), map(x => o[x] = f(o[x])) (keys(o)), o);

Zeyilname - nesneler neden varsayılan olarak yinelenemez?

ES2015, yineleyiciyi ve yinelenebilir protokolleri belirtmiştir. Ancak nesneler hala tekrarlanabilir değildir ve bu nedenle eşlenemez. Bunun nedeni, verilerin ve program seviyesinin karıştırılmasıdır .


1
Biraz fazla mühendis gibi görünüyor; Aslında bir döngü için 6 fonksiyon sayıyorum. Diğer çözümler çok daha basittir ve kabul edilen cevap da 5 kat daha hızlıdır.
fregante

4
@ bfred.it Yorumunuzun amacı nedir? Mikro optimizasyonu seviyorsanız da kullanmamalısınız Array.prototype.reduce. Burada göstermek istediğim tek şey, kabul edilen cevabın bir şekilde "suistimaller" Array.prototype.reduceve tamamen işlevsel bir haritalamanın nasıl uygulanabileceğidir. İşlevsel programlama ile ilgilenmiyorsanız, cevabımı görmezden gelmelisiniz.

2
"indirgeme kompozit tipin yapısını değiştirmek için araçlar" Bunun doğru olduğunu düşünmüyorum. Aynı uzunlukta ve hatta aynı değerlerde yeni bir dizi üreten bir Array.reduce mükemmel bir şekilde meşrudur. Küçültme, harita ve / veya filtrenin işlevselliğini yeniden oluşturmak için kullanılabilir (veya her ikisi de, karmaşık bir dönüştürücüde olduğu gibi, azaltmanın temelidir). FP'de bu bir tür kıvrımdır ve aynı türle sonuçlanan bir kıvrım hala bir kıvrımdır.
Dtipson

2
@Dtipson Kesinlikle haklısın. A fold, bir map(işlev) ' den daha geneldir . Ancak, bu benim 2016 ortasındaki bilgimdi. Bu yarım bir sonsuzluk: D

1
Ha, evet. Tüm bu şeylerin ne kadar birbirine bağlı olduğunu ve daha geniş terim ve arayüz ekosistemini fark etmem yıllar aldı. Bu kadar kolay gözüken şeylerin imkansız bir şekilde karmaşık olduğu ortaya çıkıyor ve imkansız derecede karmaşık görünen bazı şeyler oldukça düzgün bir şekilde uzaklaşıyor. :)
Dtipson

10

JavaScript yeni Object.fromEntriesyöntemi aldı.

Misal

function mapObject (obj, fn) {
  return Object.fromEntries(
    Object
      .entries(obj)
      .map(fn)
  )
}

const myObject = { a: 1, b: 2, c: 3 }
const myNewObject = mapObject(myObject, ([key, value]) => ([key, value * value]))
console.log(myNewObject)

açıklama

Yukarıdaki kod, Object'i [[<key>,<value>], ...]eşleyebileceğiniz iç içe bir Array ( ) biçimine dönüştürür . Object.fromEntriesDiziyi tekrar bir Nesneye dönüştürür.

Bu modelle ilgili en güzel şey, haritalama sırasında artık nesne anahtarlarını kolayca dikkate alabilmenizdir.

belgeleme

Tarayıcı Desteği

Object.fromEntriesşu anda yalnızca bu tarayıcılar / motorlar tarafından desteklenmektedir , bununla birlikte çoklu dolgular mevcuttur (örn. @ babel / polyfill ).


2
Temel olarak, Object.fromEntriesbunun tam tersidir Object.entries. Object.entriesbir nesneyi anahtar / değer çiftleri listesine dönüştürür. Object.fromEntriesanahtar / değer çiftlerinin listesini bir nesneye dönüştürür.
orad

8

Minimum sürüm (es6):

Object.entries(obj).reduce((a, [k, v]) => (a[k] = v * v, a), {})

Bu bir yazım hatası nedeniyle yanlış olduğunu düşünüyorum, sanırım => Object.entries(obj).reduce((a, [k, v]) => [a[k] = v * v, a], {}), parantez yerine açılı parantez demek .
Alexander Mills

@AlexanderMills, kodum doğru. Parantez içindeki virgül operatörü hakkında daha fazla bilgi edinin: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Yukulélé

Anladım, bir dahaki sefere bunu açıklamak isteyebilirsiniz, ama sanırım yorumların ne olduğunu.
Alexander Mills

1
temelde, benim kod eşdeğer:Object.entries(obj).reduce((a, [k, v]) => {a[k] = v * v; return a}, {})
Yukulélé

1
Mükemmel cevap. Object.entries().reduceES6 + ile düşündüğüm en iyi çözüm. Daha returnziyade redüktörde bir ifade kullandıysa implicit returnve commaoperatör - IMHO
Drenai

7

Maksimum performans için.

Nesneniz sık sık değişmiyor, ancak sık sık yinelenmesi gerekiyorsa, yerel bir haritayı önbellek olarak kullanmanızı öneririz.

// 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 zaten Chrome, Edge, Firefox ve beta Opera'da çalışıyor, bu yüzden geleceğe dönük bir özellik. ES7'den geliyor, bu yüzden çalışmadığı IE için https://github.com/es-shims/Object.entries doldurun .


Yıkıcı kullanmaya ne dersiniz ?
Константин Ван

1
@ K._ eskiden çok yavaştı, ama şimdi performansı bilmiyorum. Görünüşe göre V8 v 5.6, yıkım için bazı optimizasyonlar getirdi, ancak bu ölçülmelidir v8project.blogspot.co.uk
Pawel

Veya daha az performanslı es7 ama değişmez:const fn = v => v * 2; const newObj = Object.entries(myObject).reduce((acc, [k,v]) => Object.assign({}, acc, {[k]: fn(v)}), {});
mikebridge

Diğer yanıtların hiçbirinin neden Object.entries kullanmadığını merak ediyorum. Anahtarları yinelemekten ve obj [key] kullanmaktan çok daha temiz.
corwin.amber

6

mapyöntemi ve forEachdizileri kullanabilirsiniz , ancak kullanmak istiyorsanız Objecto zaman aşağıdaki gibi bükülme ile kullanabilirsiniz:

Javascript Kullanma (ES6)

var obj = { 'a': 2, 'b': 4, 'c': 6 };   
Object.entries(obj).map( v => obj[v[0]] *= v[1] );
console.log(obj); //it will log as {a: 4, b: 16, c: 36}

var obj2 = { 'a': 4, 'b': 8, 'c': 10 };
Object.entries(obj2).forEach( v => obj2[v[0]] *= v[1] );
console.log(obj2); //it will log as {a: 16, b: 64, c: 100}

JQuery kullanma

var ob = { 'a': 2, 'b': 4, 'c': 6 };
$.map(ob, function (val, key) {
   ob[key] *= val;
});
console.log(ob) //it will log as {a: 4, b: 16, c: 36}

Veya $.eachaşağıdaki örnekte olduğu gibi yöntem gibi diğer döngüler de kullanabilirsiniz :

$.each(ob,function (key, value) {
  ob[key] *= value;
});
console.log(ob) //it will also log as {a: 4, b: 16, c: 36}

$JQuery nerede ?
masterxilo

Evet $ ve jQuery
Haritsinh Gohil

1
@Ronald yanlış anladım, güncellenmiş cevabımı görüyorum, aşağı oy vermediğin için gerçekten hata yaptığım için teşekkürler, topluluğumuzu geliştirdiğin için teşekkürler.
Haritsinh Gohil

@bcoughlan evet tam olarak ben de yorum yazdım, bu sayıların kareleri, o zaman ne istiyorsun?
Haritsinh Gohil

1
@HaritsinhGohil Onu bir jQuery çözümü verdiğiniz için eleştirdiği anlamına geldim. Bugünlerde jQuery'den uzaklaşmak için bazı itici güçler olduğu ve elbette Node olduğu doğrudur, ancak bir OP özellikle saf JS veya Node istemediği sürece, birisinin bir web ortamında çalıştığını ve bu jQuery olduğunu varsaymanın iyi olduğunu düşünüyorum. neredeyse kesin olarak kullanılabilir.
abalter

4

Üzerinde map functionmevcut değil Object.prototypeancak öykünebilir

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;
});

Performans sorunları: typeof callback === 'function'kesinlikle gereksiz. 1) mapgeri arama olmadan hiçbir anlamı yoktur 2) callbackişlev değilse, sizin mapuygulamanız sadece döngü için anlamsız çalışır. Ayrıca, Object.prototype.hasOwnProperty.call( obj, key )biraz overkill.
ankhzet

3

Bunu, bunu yapmayı öğrenmeye çalışan bir Google aramasında ilk öğe olarak gördüm ve diğer son zamanlarda bunu bulduğum çözümü bulduğum ve npm paketini değiştiremeyen bir çözüm bulduğumu düşündüm.

Değişmez, kendi belgelerinde OP'nin EXACT durumunu kullandığından paylaşmanın ilginç olduğunu düşünüyorum - aşağıdaki kendi kodum değil, mevcut immutable-js belgelerinden çekildi:

const { Seq } = require('immutable')
const myObject = { a: 1, b: 2, c: 3 }
Seq(myObject).map(x => x * x).toObject();
// { a: 1, b: 4, c: 9 } 

Seq'in başka özellikleri olmadığı için ("Seq, ara koleksiyonlar oluşturmadan tüm üst düzey toplama yöntemlerinin (harita ve filtre gibi) kullanımını etkin bir şekilde zincirlemelerine izin veren tembel bir işlemi açıklar") ve diğer bazı değiştirilemez js verilerinin yapılar da işi oldukça verimli bir şekilde yapabilir.

Bu yöntemi kullanan herkes elbette npm install immutabledokümanları okumak zorunda kalacak ve okumak isteyebilir:

https://facebook.github.io/immutable-js/


3

DÜZENLEME: Daha yeni JavaScript özelliklerini kullanmanın standart yolu -

const identity = x =>
  x

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

oBazı nesneler nerede ve fharitalama fonksiyonunuz. Ya da, bir fonksiyon a -> bve tip değerleri olan bir nesne verildiğinde , tip değerleri olan abir nesne ürettiğimizi söyleyebiliriz b. Yalancı tip imza olarak -

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

Orijinal cevap, mapReducedönüşümümüzü farklı bir şekilde düşünmemizi sağlayan güçlü bir birleştiriciyi göstermek için yazılmıştır.

  1. m, eşleme fonksiyonu - size gelen elemanı daha önce dönüştürme şansı verir…
  2. r, azaltma işlevi - bu işlev, akümülatörü eşlenen öğenin sonucu ile birleştirir

sezgisel, mapReduce doğrudan takabileceğimiz yeni bir redüktör oluşturur Array.prototype.reduce. Ama daha da önemlisi, bizim nesne funktoru uygulanmasını uygulayabilir omapnesne Monoid kullanılarak açıkça, Object.assignve {}.

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 }

Programın aslında yazmamız gereken tek kısmının haritalama uygulamasının kendisinin olduğuna dikkat edin -

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

Bilinen bir nesne ove bazı anahtarlar göz önüne alındığında k, hesaplanan özelliği anahtarın değerinin kçağrılması sonucu olan bir nesne oluşturur .fo[k]

mapReduceİlk soyutlama yaparsak, sıralama potansiyeline bir göz atarız.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
    )

Her şey aynı şekilde çalışır, ancak omapşimdi daha yüksek bir düzeyde tanımlanabilir. Tabii ki yeni Object.entries, bunu aptalca gösteriyor, ancak egzersiz hala öğrenci için önemlidir.

mapReduceBurada tam potansiyeli görmeyeceksiniz , ancak bu cevabı paylaşıyorum çünkü kaç yere uygulanabileceğini görmek ilginç. Nasıl türetildiği ve faydalı olabileceği diğer yollarla ilgileniyorsanız, lütfen bu cevaba bakın .


4
Kullanalım Mapve Map.entriesOK: D. Harita veri türleri olarak düz nesneleri kötüye kullanmaktan bıktım.

2
Kabul ediyorum Mapmümkün olduğunda / mümkün olduğunda kullanılmalıdır, ancak bu prosedürleri düz JS nesnelerinde kullanma gereğinin tamamen yerini almaz tho: D
Teşekkür ederim

2

@Amberlamps cevabını temel alan bir yardımcı program işlevi (yorum olarak çirkin görünüyordu)

function mapObject(obj, mapFunc){
    return Object.keys(obj).reduce(function(newObj, value) {
        newObj[value] = mapFunc(obj[value]);
        return newObj;
    }, {});
}

ve kullanımı:

var obj = {a:1, b:3, c:5}
function double(x){return x * 2}

var newObj = mapObject(obj, double);
//=>  {a: 2, b: 6, c: 10}

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


Object.prototype.map = function(fn){
    var oReturn = {};
    for (sCurObjectPropertyName in this) {
        oReturn[sCurObjectPropertyName] = fn(this[sCurObjectPropertyName], sCurObjectPropertyName);
    }
    return oReturn;
}
Object.defineProperty(Object.prototype,'map',{enumerable:false});





newObject = myObject.map(function (value, label) {
    return value * value;
});


// newObject is now { 'a': 1, 'b': 4, 'c': 9 }

enumerablevarsayılanfalse
Teşekkürler

2

Yanıtım büyük ölçüde buradaki en yüksek puan alan cevaba dayanıyor ve umarım herkes anlar (GitHub'mda da aynı açıklamaya sahip). Bu yüzden harita ile ilişkilendirilmesi işe yarıyor:

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

İşlevin amacı, bir dizi döndürmeden tüm nesneler (nesneler ve diziler) için kullanılabilir bir yöntemi kullanarak bir nesneyi alıp nesnenin orijinal içeriğini değiştirmektir. JS içindeki hemen hemen her şey bir nesnedir ve bu nedenle miras boru hattının aşağısında yer alan unsurlar, potansiyel olarak teknik olarak satırdakiler için kullanılabilir olanları kullanabilir (ve bunun tersi).

Bunun nedeni, varolan bir nesneyi değiştirmek yerine bir dizinin açık veya örtük RETURN'unu sağladığınız GEREKTİREN bir diziyi döndüren .map işlevlerinden kaynaklanmaktadır. Aslında, nesnenin bir dizi olduğunu düşünmek için programı kandırırsınız, bu da harita işlevini, tek tek tuşların ilişkili olduğu değerlerle hareket ederek kullanmanıza izin verir (aslında yanlışlıkla diziler döndürdüm, ancak düzelttim). Normal anlamda bir geri dönüş olmadığı sürece, orijinal nesne stili bozulmadan oluşturulan ve programlandığı gibi değiştirilen bir dizi olmayacaktır.

Bu özel program, görüntüler adı verilen bir nesneyi alır ve anahtarlarının değerlerini alır ve başka bir işlevde kullanmak üzere URL etiketlerini ekler. Orijinal bu:

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' };

... ve değiştirildi:

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') 
};

Nesnenin orijinal yapısı bozulmadan bırakılır ve geri dönüş olmadığı sürece normal özellik erişimine izin verilir. Normal gibi bir dizi döndürmeyin ve her şey iyi olacak. Amaç, orijinal değerleri (görüntüler [anahtar]) başka bir şeye değil, istenen şeye YENİDEN TASARLAMAKTIR. Bildiğim kadarıyla, dizi çıktısını önlemek için görüntü [anahtar] REASSIGNMENT olmalı ve bir dizi döndürmek için örtük veya açık bir istek (değişken ataması bunu yapar ve benim için ileri geri aksaklık) vardı.

DÜZENLE:

Orijinal nesneyi değiştirmekten kaçınmak için yeni nesne oluşturma ile ilgili diğer yöntemini ele alacak (ve yanlışlıkla çıkış olarak bir dizi oluşturmayı önlemek için yeniden atama gerekli görünmektedir). Bu işlevler ok sözdizimini kullanır ve ileride kullanmak üzere yeni bir nesne oluşturmak istiyorsanız kullanılır.

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

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

Bu işlevlerin çalışma şekli şöyledir:

mapFn daha sonra eklenecek işlevi alır (bu durumda (değer) => değer) ve mapFn (burada olduğu gibi döndürdüğünüz değeri değiştirirseniz iki ile çarpılır) olarak saklanan her şeyi döndürür obj) [anahtar],

ve sonra sonuçtaki anahtarla ilişkili orijinal değeri yeniden tanımlar [key] = mapFn (obj) [key]

ve sonuçta gerçekleştirilen işlemi döndürür (.reduce fonksiyonunun sonunda başlatılan parantez içindeki akümülatör).

Tüm bunlar seçilen nesne üzerinde yapılıyor ve STILL, döndürülen bir dizi için örtük bir istek OLAMAZ ve sadece değerleri anlayabildiğim kadarıyla yeniden atadığımda çalışır. Bu, bazı zihinsel jimnastik gerektirir, ancak yukarıda görülebileceği gibi kod satırlarını azaltır. Çıktı tam olarak aşağıda görüldüğü gibidir:

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

Bunun NUMARA OLMAYANLAR ile çalıştığını unutmayın. MapFN işlevinde DEĞERİ GERİ DÖNDÜREN HERHANGİ BİR nesneyi çoğaltabilirsiniz.


2

İlk fonksiyon soruyu cevaplar. Bir harita oluşturur.

İkinci işlev harita oluşturmaz. Bunun yerine, varolan nesnedeki özellikleri kullanarak döngüler hasOwnProperty(). Bu harita alternatifi bazı durumlarda daha iyi bir çözüm olabilir.

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


//creates a map (answers question, but function below is 
//much better in some situations)
var newObject = {};
makeMap();    
function makeMap() {
    for (var k in myObject) {
        var value = myObject[k];
        newObject[k] = value * value;
    }
    console.log(newObject); //mapped array
}


//Doesn't create a map, just applies the function to
//a specific property using existing data
function getValue(key) {
  for (var k in myObject) {
    if (myObject.hasOwnProperty(key)) {
      var value = myObject[key]
      return value * value; //stops iteration
    }
  }
}
Input: <input id="input" value="" placeholder="a, b or c"><br>
Output:<input id="output"><br>
<button onclick="output.value=getValue(input.value)" >Get value</button>


2
Bu orijinal soruya cevap vermez - değerleri sağlanan bir işlevle yeni bir nesneye eşlemez (yani, Array.prototype.map gibi bir şey değildir).
Matt Browne

@MattBrowne Tartışmalı bir harita olanı yaratan ikinci bir yöntem ekledim. Yavaş ama OP'nin istediği şeyi yapıyor. İlk yöntem birçok durumda idealdir, bu yüzden bir döngü ve özellik işlevleri kullandım.
Victor Stoddard

1

mapSadece değerleri değil, aynı zamanda tuşları da pingle ilgileniyorsanız , yazdım Object.map(valueMapper, keyMapper), bu böyle davranıyor:

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 }

3
Sanırım temelde sadece cevap olarak bir link verdiniz, ki bu da kaşlarını çattı.
Chris Wright

Herkes için faydalı olursa npm install @mattisg/object.map.
MattiSG

1

Anahtarları da değiştirmeye izin veren bir sürüm gerekiyordu (@Amberlamps ve @ yonatanmn cevaplara dayalı);

var facts = [ // can be an object or array - see jsfiddle below
    {uuid:"asdfasdf",color:"red"},
    {uuid:"sdfgsdfg",color:"green"},
    {uuid:"dfghdfgh",color:"blue"}
];

var factObject = mapObject({}, facts, function(key, item) {
    return [item.uuid, {test:item.color, oldKey:key}];
});

function mapObject(empty, obj, mapFunc){
    return Object.keys(obj).reduce(function(newObj, key) {
        var kvPair = mapFunc(key, obj[key]);
        newObj[kvPair[0]] = kvPair[1];
        return newObj;
    }, empty);
}

factObject =

{
"asdfasdf": {"color":"red","oldKey":"0"},
"sdfgsdfg": {"color":"green","oldKey":"1"},
"dfghdfgh": {"color":"blue","oldKey":"2"}
}

Düzenleme: başlangıç ​​nesnesine {} geçmek için hafif bir değişiklik. [] Olmasına izin verir (tuşlar tamsayı ise)


1

Özellikle tek bir nesne için diziler için kullandığım işlevi kullanmak istedim ve basit tutmak istedim. Bu benim için çalıştı:

var mapped = [item].map(myMapFunction).pop();

Bu hiç de farklı değilvar mapped = myMapFunction(item)
Teşekkürler

Bu, burada gördüğüm diğer tüm "roket bilimi" çözümlerinden çok daha basit. Paylaştığınız için teşekkürler :)
Yuri Teixeira

1

OP'nin tam olarak ne istediğine daha yakından yanıt vermek için OP bir nesne ister:

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

bir harita yöntemine sahip olmak myObject.map,

aşağıdaki gibi kullanılacak Array.prototype.map benzeri:

newObject = myObject.map (işlev (değer; etiket) {
    dönüş değeri * değer;
});
// newObject artık {'a': 1, 'b': 4, 'c': 9}

En iyi imho ( " sorulana yakın " + "ES {5,6,7} gereksiz yere gerekli değil " olarak ölçülür ) yanıtı:

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;
}

Yukarıdaki kod, yalnızca son ECMAScript sürümlerinde bulunan dil özelliklerini kullanmaktan kasıtlı olarak kaçınır. Yukarıdaki kod ile sorun lke bu çözülebilir:

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);
alternatif test kodu burada

Bazıları tarafından kaşlarını çatmış olmasının yanı sıra, çözümü prototip zincirine böyle eklemek de mümkün olacaktır.

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;
}

Dikkatli bir gözetim ile yapıldığında map, diğer nesnelerin (yani, Array'ın map) herhangi bir kötü etkisi olmamalı ve darbe yöntemi olmamalıdır .



1

MapEntries işlevini tanımlayın.

mapEntries, nesnedeki her girişte value, key ve object parametreleriyle çağrılan bir geri çağırma işlevi alır. Yeni bir değer döndürmelidir.

mapEntries, geri çağrıdan döndürülen yeni değerlerle yeni bir nesne döndürmelidir.

Object.defineProperty(Object.prototype, 'mapEntries', {
  enumerable: false,
  value: function (mapEntriesCallback) {
    return Object.fromEntries(
      Object.entries(this).map(
        ([key, value]) => [key, mapEntriesCallback(value, key, this)]
      )
    )
  }
})


// Usage example:

var object = {a: 1, b: 2, c: 3}
var newObject = object.mapEntries(value => value * value)
console.log(newObject)
//> {a: 1, b: 4, c: 9}

Düzenleme: Önceki bir sürüm, bunun numaralandırılabilir bir özellik olmadığını belirtmedi


0

Hey, yardımcı olabilecek küçük bir haritacı işlevi yazdı.

    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];
                }
              }
            }
         }
      }

1
Sanırım "Hey" yerine "Ben" demek
Carlo

0

Farklı bir bakış, derin nesneler üzerinde de çalışabilen özel bir json stringify işlevi kullanmaktır. Yine de sunucuya json olarak göndermeyi düşünüyorsanız bu yararlı olabilir

const obj = { 'a': 1, 'b': 2, x: {'c': 3 }}
const json = JSON.stringify(obj, (k, v) => typeof v === 'number' ? v * v : v)

console.log(json)
console.log('back to json:', JSON.parse(json))


0

Muafiyetleri azaltmak için sadece dizeleri ele alıyorum:

Object.keys(params).map(k => typeof params[k] == "string" ? params[k] = params[k].trim() : null);

0

TypeScript'te Nesne Eşleyici

Kullandığım örneklere benzer Object.fromEntriesgibi bu bir , ama yine de onlar kullanımı çok kolay değildir. Kullanan Object.keysve sonra cevaplar keyaslında gerekli olmayabilir birden fazla arama yapıyor.

Bir yoktu diledi Object.mapfonksiyonu, ama biz kendi Our oluşturup diyebilirsiniz objectMaphem değiştirme yeteneği ile keyve value:

Kullanım (JavaScript):

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

// keep the key and modify the value
let obj = objectMap(myObject, val => val * 2);
// obj = { a: 2, b: 4, c: 6 }


// modify both key and value
obj = objectMap(myObject,
    val => val * 2 + '',
    key => (key + key).toUpperCase());
// obj = { AA: '2', BB: '4', CC: '6' }

Kod (TypeScript):

interface Dictionary<T> {
    [key: string]: T;
}

function objectMap<TValue, TResult>(
    obj: Dictionary<TValue>,
    valSelector: (val: TValue, obj: Dictionary<TValue>) => TResult,
    keySelector?: (key: string, obj: Dictionary<TValue>) => string,
    ctx?: Dictionary<TValue>
) {
    const ret = {} as Dictionary<TResult>;
    for (const key of Object.keys(obj)) {
        const retKey = keySelector
            ? keySelector.call(ctx || null, key, obj)
            : key;
        const retVal = valSelector.call(ctx || null, obj[key], obj);
        ret[retKey] = retVal;
    }
    return ret;
}

TypeScript kullanmıyorsanız , JavaScript kodunu almak için yukarıdaki kodu TypeScript Playground'a kopyalayın .

Ayrıca, nedeni koymak keySelectorsonravalSelector parametre listesine , isteğe bağlı olmasıdır.

* Bazı krediler Alexander-Mills'in cevabına gidiyor .


0
const mapObject = (targetObject, callbackFn) => {
    if (!targetObject) return targetObject;
    if (Array.isArray(targetObject)){
        return targetObject.map((v)=>mapObject(v, callbackFn))
    }
    return Object.entries(targetObject).reduce((acc,[key, value]) => {
        const res = callbackFn(key, value);
        if (!Array.isArray(res) && typeof res ==='object'){
            return {...acc, [key]: mapObject(res, callbackFn)}
        }
        if (Array.isArray(res)){
            return {...acc, [key]: res.map((v)=>mapObject(v, callbackFn))}
        }
        return {...acc, [key]: res};
    },{})
};
const mapped = mapObject(a,(key,value)=> {
    if (!Array.isArray(value) && key === 'a') return ;
    if (!Array.isArray(value) && key === 'e') return [];
    if (!Array.isArray(value) && key === 'g') return value * value;
    return value;
});
console.log(JSON.stringify(mapped)); 
// {"b":2,"c":[{"d":2,"e":[],"f":[{"g":4}]}]}

Bu işlev, özyinelemeli olarak nesneye ve nesnelerin dizilerine gider. Tanımsız döndürülürse öznitelikler silinebilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.