Javascript nesnesindeki bir anahtarı yeniden adlandırmanın akıllı (yani optimize edilmiş) bir yolu var mı?
Optimize edilmemiş bir yol:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Javascript nesnesindeki bir anahtarı yeniden adlandırmanın akıllı (yani optimize edilmiş) bir yolu var mı?
Optimize edilmemiş bir yol:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Yanıtlar:
Bunu yapmanın en eksiksiz (ve doğru) yolu olduğuna inanıyorum:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Bu yöntem, yeniden adlandırılan özelliğin orijinal özellikle aynı şekilde davranmasını sağlar .
Ayrıca bana öyle geliyor ki, bunu bir fonksiyona / yönteme koyup içine koyma olanağının Object.prototype
sorunuzla ilgisi yok.
if (old_key !== new_key)
to: if (old_key !== new_key && o[old_key])
Çalışmayı bir işlevde sarabilir ve Object
prototipe atayabilirsiniz . Belki birden fazla yeniden adlandırma akışı yapmak için akıcı arayüz stilini kullanın.
Object.prototype.renameProperty = function (oldName, newName) {
// Do nothing if the names are the same
if (oldName === newName) {
return this;
}
// Check for the old property name to avoid a ReferenceError in strict mode.
if (this.hasOwnProperty(oldName)) {
this[newName] = this[oldName];
delete this[oldName];
}
return this;
};
ECMAScript 5'e Özel
Keşke sözdizimi bu karmaşık olmasaydı ama kesinlikle daha fazla kontrole sahip olmak güzel.
Object.defineProperty(
Object.prototype,
'renameProperty',
{
writable : false, // Cannot alter this property
enumerable : false, // Will not show up in a for-in loop.
configurable : false, // Cannot be deleted via the delete operator
value : function (oldName, newName) {
// Do nothing if the names are the same
if (oldName === newName) {
return this;
}
// Check for the old property name to
// avoid a ReferenceError in strict mode.
if (this.hasOwnProperty(oldName)) {
this[newName] = this[oldName];
delete this[oldName];
}
return this;
}
}
);
Object.defineProperty
.
hasOwnProperty
özellikleri kontrol etmek ve for ... in
döngüler içinde kullanmak için uygun bir uygulama varsa, Object genişletirsek neden önemlidir?
Kaynak nesnenizi değiştiriyorsanız, ES6 bunu bir satırda yapabilir.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Veya yeni bir nesne oluşturmak istiyorsanız iki satır.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
etrafında köşeli ayraç var newKey
? Çözüm aslında bu olmadan çalışır.
Birinin bir özellik listesini yeniden adlandırması gerekirse:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Kullanımı:
const obj = { a: "1", b: "2" };
const newKeys = { a: "A", c: "C" };
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
// {A:"1", b:"2"}
my_object_property
için myObjectProperty
zaman özelliği, tek-ifadeli ise, bununla birlikte, daha sonra anahtar uzaklaştırılmıştır. +1
ES6(ES2015)
yolu kullanmak istiyorum !zamana ayak uydurmamız gerekiyor!
const old_obj = {
k1: `111`,
k2: `222`,
k3: `333`
};
console.log(`old_obj =\n`, old_obj);
// {k1: "111", k2: "222", k3: "333"}
/**
* @author xgqfrms
* @description ES6 ...spread & Destructuring Assignment
*/
const {
k1: kA,
k2: kB,
k3: kC,
} = {...old_obj}
console.log(`kA = ${kA},`, `kB = ${kB},`, `kC = ${kC}\n`);
// kA = 111, kB = 222, kC = 333
const new_obj = Object.assign(
{},
{
kA,
kB,
kC
}
);
console.log(`new_obj =\n`, new_obj);
// {kA: "111", kB: "222", kC: "333"}
Verilerinizi değiştirmek istemiyorsanız, bu işlevi göz önünde bulundurun ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Yazeed Bzadough'un kapsamlı bir açıklaması https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
Buradaki yanıtların çoğu JS Nesnesi anahtar / değer çiftleri sırasını koruyamaz. Ekranda değiştirmek istediğiniz bir nesne anahtar / değer çifti biçiminiz varsa, nesne girişlerinin sırasını korumak önemlidir.
JS nesnesinde döngü ve anahtar / değer çiftini değiştirilmiş bir anahtar adıyla yeni çiftle değiştirmenin ES6 yolu şöyle olacaktır:
let newWordsObject = {};
Object.keys(oldObject).forEach(key => {
if (key === oldKey) {
let newPair = { [newKey]: oldObject[oldKey] };
newWordsObject = { ...newWordsObject, ...newPair }
} else {
newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
}
});
Çözüm, eskisinin yerine yeni girişi ekleyerek girişlerin sırasını korur.
Lodash'ı deneyebilirsiniz _.mapKeys
.
var user = {
name: "Andrew",
id: 25,
reported: false
};
var renamed = _.mapKeys(user, function(value, key) {
return key + "_" + user.id;
});
console.log(renamed);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
Nesne yok etme ve yayma işlecini kullanan bir varyasyon:
const old_obj = {
k1: `111`,
k2: `222`,
k3: `333`
};
// destructuring, with renaming. The variable 'rest' will hold those values not assigned to kA, kB, or kC.
const {
k1: kA,
k2: kB,
k3: kC,
...rest
} = old_obj;
// now create a new object, with the renamed properties kA, kB, kC;
// spread the remaining original properties in the 'rest' variable
const newObj = {kA, kB, kC, ...rest};
Kişisel olarak, ekstra ağır eklentiler ve tekerlekler uygulamadan nesnedeki anahtarları yeniden adlandırmanın en etkili yolu:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
try-catch
Nesneniz geçersiz bir yapıya sahipse bunu da içine alabilirsiniz . Mükemmel çalışıyor :)
'a'
bölgesi { a: 1, aa: 2, aaa: 3}
veya daha fazla dizeleri veya numaraları veya boolelerde daha bir şey değerlere sahip bir nesneyi yeniden adlandırmak deneyin veya dairesel referanslarla deneyin.
Böyle bir şey yapardım:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Kavramsal bir bakış açısından eski nesneyi (web hizmetinden olanı) olduğu gibi bırakmanın ve ihtiyacınız olan değerleri yeni bir nesneye koymanın daha iyi olacağını söyleyebilirim. İstemcide değilse, en azından sunucuda, bir noktada veya başka bir yerde belirli alanları ayıkladığınızı varsayıyorum. Web hizmetindekilerle aynı olan alan adlarını, yalnızca küçük harf kullanmayı seçtiyseniz, bunu gerçekten değiştirmez. Yani, böyle bir şey yapmanızı tavsiye ederim:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Tabii ki, burada doğru olmayabilecek her türlü varsayımı yapıyorum. Bu sizin için geçerli değilse veya çok yavaşsa (test etmedim, ancak alan sayısı arttıkça farkın küçüldüğünü hayal ediyorum), lütfen bunların tümünü göz ardı edin :)
Bunu yapmak istemiyorsanız ve yalnızca belirli tarayıcıları desteklemeniz gerekiyorsa, yeni alıcıları da "büyük harf (alan)" döndürmek için de kullanabilirsiniz: bkz. Http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-samples-and-demolar / ve daha fazla bilgi için bu sayfadaki bağlantılar.
DÜZENLE:
İnanılmaz bir şekilde, bu aynı zamanda neredeyse iki kat daha hızlı, en azından benim işyerindeki FF3.5'imde. Bkz. Http://jsperf.com/spiny001
Bu, bir anahtarı yeniden adlandırmak için tam olarak daha iyi bir çözüm sunmasa da, içerdikleri verileri mutasyona uğratmadan bir nesnedeki tüm anahtarları yeniden adlandırmanın hızlı ve kolay bir ES6 yolu sağlar.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Bu sayfada listelenen çözümlerin bazılarının bazı yan etkileri vardır:
Anahtarın konumunu aynı yerde tutan ve IE9 + 'da uyumlu olan, ancak yeni bir nesne oluşturmak zorunda olan ve en hızlı çözüm olmayabilecek bir çözüm:
function renameObjectKey(oldObj, oldName, newName) {
const newObj = {};
Object.keys(oldObj).forEach(key => {
const value = oldObj[key];
if (key === oldName) {
newObj[newName] = value;
} else {
newObj[key] = value;
}
});
return newObj;
}
Lütfen dikkat: IE9 katı modda her desteği desteklemeyebilir
En güçlü REDUCE yöntemi ile başka bir yol .
data = {key1: "value1", key2: "value2", key3: "value3"};
keyMap = {key1: "firstkey", key2: "secondkey", key3: "thirdkey"};
mappedData = Object.keys(keyMap).reduce((obj,k) => Object.assign(obj, { [keyMap[k]]: data[k] }),{});
console.log(mappedData);
Bu, bombacının işlevinde yaptığım küçük bir değişikliktir; Yalnızca bir nesne yerine bir Nesne Dizisi alabilmek ve ayrıca dizini etkinleştirebilirsiniz. ayrıca "Anahtarlar" bir dizi tarafından atanabilir
function renameKeys(arrayObject, newKeys, index = false) {
let newArray = [];
arrayObject.forEach((obj,item)=>{
const keyValues = Object.keys(obj).map((key,i) => {
return {[newKeys[i] || key]:obj[key]}
});
let id = (index) ? {'ID':item} : {};
newArray.push(Object.assign(id, ...keyValues));
});
return newArray;
}
Ölçek
const obj = [{ a: "1", b: "2" }, { a: "5", b: "4" } ,{ a: "3", b: "0" }];
const newKeys = ["A","C"];
const renamedObj = renameKeys(obj, newKeys);
console.log(renamedObj);
Bence yolunuz optimize edildi. Ama yeniden sıralanmış anahtarlarla sonuçlanacaksınız. Yeni oluşturulan anahtarın sonuna eklenir. Asla anahtar düzene güvenmemeniz gerektiğini biliyorum, ancak korumanız gerekiyorsa, tüm anahtarları gözden geçirmeniz ve söz konusu işlem sırasında söz konusu anahtarı değiştirerek yeni bir nesne oluşturmanız gerekir.
Bunun gibi:
var new_o={};
for (var i in o)
{
if (i==old_key) new_o[new_key]=o[old_key];
else new_o[i]=o[i];
}
o=new_o;
npm i paix
import { paix } from 'paix';
const source_object = { FirstName: "Jhon", LastName: "Doe", Ignored: true };
const replacement = { FirstName: 'first_name', LastName: 'last_name' };
const modified_object = paix(source_object, replacement);
console.log(modified_object);
// { Ignored: true, first_name: 'Jhon', last_name: 'Doe' };