Чи є розумний (тобто оптимізований) спосіб перейменувати ключ в об’єкті JavaScript?
Неоптимізованим способом буде:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Чи є розумний (тобто оптимізований) спосіб перейменувати ключ в об’єкті JavaScript?
Неоптимізованим способом буде:
o[ new_key ] = o[ old_key ];
delete o[ old_key ];
Відповіді:
Я вважаю, що найбільш повним (і правильним) способом цього є:
if (old_key !== new_key) {
Object.defineProperty(o, new_key,
Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];
}
Цей метод забезпечує, що перейменований властивість поводиться однаково з оригінальним.
Крім того, мені здається, що можливість увімкнути це у функцію / метод і вкласти це Object.prototype
не має значення стосовно вашого питання.
if (old_key !== new_key)
в: if (old_key !== new_key && o[old_key])
Ви можете зафіксувати роботу у функції та призначити її Object
прототипу. Можливо, використовуйте вільний стиль інтерфейсу, щоб зробити кілька потоків перейменованими.
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 Специфічний
Я хотів би, щоб синтаксис був не таким складним, але, безумовно, приємно мати більше контролю.
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
для перевірки властивостей і в for ... in
циклі, то чому це має значення, якщо ми розширюємо Object?
Якщо ви мутуєте свій вихідний об’єкт, ES6 може зробити це в одному рядку.
delete Object.assign(o, {[newKey]: o[oldKey] })[oldKey];
Або два рядки, якщо ви хочете створити новий об’єкт.
const newObject = {};
delete Object.assign(newObject, o, {[newKey]: o[oldKey] })[oldKey];
[]
навколо newKey
? Рішення працює без цього насправді.
Якщо комусь потрібно перейменувати список об’єктів:
function renameKeys(obj, newKeys) {
const keyValues = Object.keys(obj).map(key => {
const newKey = newKeys[key] || key;
return { [newKey]: obj[key] };
});
return Object.assign({}, ...keyValues);
}
Використання:
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
в myObjectProperty
, однак, якщо моєї власність була однією сформульованим, то ключ був видалений. +1
ES6(ES2015)
спосіб!нам потрібно йти в ногу з часом!
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"}
Якщо ви не хочете мутувати свої дані, врахуйте цю функцію ...
renameProp = (oldProp, newProp, {[oldProp]:old, ...others}) => ({
[newProp]: old,
...others
})
Ретельне пояснення Yazeed Bzadough https://medium.com/front-end-hacking/immutably-rename-object-keys-in-javascript-5f6353c7b6dd
Більшість відповідей тут не підтримують порядок пар ключ-значення JS Object. Якщо у вас на екрані є форма об'єктних пар ключ-значення, яку ви хочете змінити, наприклад, важливо зберегти порядок записів об'єктів.
Спосіб перегляду циклу через об’єкт JS та заміна пари ключ-значення на нову пару з модифікованим іменем ключа буде чимось таким:
let newWordsObject = {};
Object.keys(oldObject).forEach(key => {
if (key === oldKey) {
let newPair = { [newKey]: oldObject[oldKey] };
newWordsObject = { ...newWordsObject, ...newPair }
} else {
newWordsObject = { ...newWordsObject, [key]: oldObject[key] }
}
});
Рішення зберігає порядок записів, додаючи новий запис замість старого.
Можна спробувати лодаш _.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>
Варіант з використанням оператора руйнування об'єкта та оператора розповсюдження:
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};
Особисто найефективніший спосіб перейменувати ключі в об'єкті без використання надмірних плагінів та коліс:
var str = JSON.stringify(object);
str = str.replace(/oldKey/g, 'newKey');
str = str.replace(/oldKey2/g, 'newKey2');
object = JSON.parse(str);
Ви також можете обернути його, try-catch
якщо ваш об'єкт має неправильну структуру. Відмінно працює :)
'a'
в { a: 1, aa: 2, aaa: 3}
або спробувати перейменувати об'єкт зі значеннями, які нічого більше рядків або чисел або булеві, або спробувати з циклічними посиланнями.
Я б зробив щось подібне:
function renameKeys(dict, keyMap) {
return _.reduce(dict, function(newDict, val, oldKey) {
var newKey = keyMap[oldKey] || oldKey
newDict[newKey] = val
return newDict
}, {})
}
Я б сказав, що з концептуальної точки зору було б краще просто залишити старий об’єкт (той, який є у веб-сервісі) таким, який він є, і поставити потрібні вам значення в новий об’єкт. Я припускаю, що ви витягуєте конкретні поля в тій чи іншій точці, якщо не на клієнті, то принаймні на сервері. Те, що ви вирішили використовувати імена полів, які є такими ж, як у веб-сервісу, лише малі регістри, насправді це не змінює. Отже, я б радив зробити щось подібне:
var myObj = {
field1: theirObj.FIELD1,
field2: theirObj.FIELD2,
(etc)
}
Звичайно, я роблю тут всілякі припущення, що може бути неправдою. Якщо це не стосується вас, або якщо це занадто повільно (чи не так? Я не перевіряв, але я думаю, що різниця зменшується, оскільки кількість полів збільшується), будь ласка, проігноруйте все це :)
Якщо ви не хочете цього робити, і вам потрібно підтримувати лише певні веб-переглядачі, ви також можете скористатися новими геттерами, щоб також повернути "верхній регістр (поле)": див. Http://robertnyman.com/2009/05/28 / getters-and-setters-with-javascript-code-sample-sample-demo / та посилання на цій сторінці для отримання додаткової інформації.
Редагувати:
Неймовірно, що це також майже вдвічі швидше, принаймні на моєму FF3.5 на роботі. Дивіться: http://jsperf.com/spiny001
Хоча це точно не дає кращого рішення для перейменування ключа, він забезпечує швидкий та простий спосіб ES6 для перейменування всіх ключів в об’єкті, не мутуючи дані, які вони містять.
let b = {a: ["1"], b:["2"]};
Object.keys(b).map(id => {
b[`root_${id}`] = [...b[id]];
delete b[id];
});
console.log(b);
Деякі з перелічених на цій сторінці рішень мають деякі побічні ефекти:
Ось рішення, яке зберігає положення ключа в тому самому місці і сумісне в IE9 +, але має створити новий об'єкт і може бути не найшвидшим рішенням:
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;
}
Зверніть увагу: IE9 може не підтримуватиEach у суворому режимі
Ще один спосіб із найпотужнішим методом ЗНИЖЕННЯ .
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);
Це невелика модифікація, яку я вніс до функції pomber; Щоб мати можливість приймати масив об'єктів замість об'єкта самостійно, а також ви можете активувати індекс. також "Ключі" можуть бути призначені масивом
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;
}
тест
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);
На ваш погляд, ваш спосіб оптимізований. Але ви закінчите з упорядкованими ключами. Щойно створений ключ буде доданий в кінці. Я знаю, що ніколи не слід покладатися на замовлення ключів, але якщо вам потрібно зберегти його, вам потрібно буде пройти всі клавіші та сконструювати новий об'єкт по черзі, замінюючи відповідний ключ під час цього процесу.
Подобається це:
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' };