#javascript
#javascript
Вопрос:
Мне предоставлен следующий объект JavaScript:
{
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
}
name
Свойство (или другие подобные сложные реквизиты) всегда предоставляется как объект внутри массива, даже если там может быть только одно значение.
Мне нужно сохранить информацию в виде объекта, который выглядит следующим образом (без массива вокруг значения name
свойства):
{
name: {
firstName: 'First ',
lastName: 'Last'
},
age: 21
}
Мне нужна универсальная функция, которая не ссылается на конкретное имя свойства, потому что оно меняется в зависимости от запроса. Вот мое решение:
const object = {
name: [{"firstName":"First ","lastName":"Last"}],
age: 21
}
const data = {}
for (const property in object) {
const value = object[property]
if (Array.isArray(value)) {
data[property] = value[0]
} else {
data[property] = value
}
}
Который возвращает правильно отформатированный объект.
Мой вопрос в том, является ли это наиболее производительным и / или наиболее очевидным способом получения результата, который я ищу?
Комментарии:
1. Судя по тому, как написан вопрос, похоже, что вы получаете объект в той же форме, в которой, по вашим словам, вы хотите его вернуть; так что либо я что-то упускаю, либо «наиболее эффективным способом» было бы вернуть тот же объект, который вы получили. Я думаю, вам нужно добавить больше деталей и контекста к вопросу.
2. @DavidsaysreinstateMonica В желаемом результате параметр name не включает массив.
3. Спасибо; может быть, все-таки пора спать…
Ответ №1:
Если вы хотите абстракцию по всему объекту, вы могли бы сделать что-то вроде этого:
const object1 = {
name: [{"firstName":"First ","lastName":"Last"}],
age: 21
}
const rebuildObject = (object) => Object.keys(object).reduce((result, key) => {
const value = object[key];
result[key] = Array.isArray(value) ? object[key][0] : value;
return resu<
}, {});
const newObject = rebuildObject(object1);
console.log(newObject);
Комментарии:
1. Отлично, это возвращает ожидаемый результат… Мне нравится, что вы использовали троичное выражение, что, безусловно, является улучшением моего оператора if / else . Я лишь немного знаком с методом reduce, мне нужно узнать о нем больше, чтобы понять, почему он лучше, чем цикл for в моем примере.
2. Небольшое замечание, чтобы иметь в виду, что это не глубокая перестройка. Поэтому, если вы хотите преобразовать объекты глубже в другую область, вам нужно расширить код. Но я сомневаюсь, что это хорошая идея, поскольку в настоящее время код преобразует каждый массив в объект. Если вы используете код для проверки, содержит ли массив несколько записей, вы можете использовать глубокое слияние, чтобы объединить их в один объект и использовать первое или последнее значение в качестве его данных.
Ответ №2:
Если name
массив гарантированно only ever have 1 object inside of it
равен и является always an array
, вы можете сделать:
const data = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
};
if(data.name.length === 0) {
const newObj = {
name: data.name[0],
age: data.age
};
};
console.log(newObj); // { firstName: 'First ', lastName: 'Last', age: 21 }
Редактировать
Когда name
на самом деле любое имя арбитражного ключа, вы можете сделать:
const data = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
};
const objKeys = Object.keys(data);
console.log(objKeys) // > Array ["name", "age"]
let arbKey = objKeys.filter(objKey => objKey !== "age")[0];
console.log(arbKey); // > "name"
const newObj = {
arbKey: data[arbKey][0],
age: data.age
};
console.log(newObj); // > Object { arbKey: Object { firstName: "First ", lastName: "Last" }, age: 21 };
Примечание: это работает только на основе предоставленной вами схемы объекта. Если ваш фактический код отличается, вам нужно будет его настроить.
Комментарии:
1. Да, массив гарантированно будет иметь только 1 объект, но имя свойства является произвольным. Это может быть
name
, это может бытьaddress
, это может бытьtheAnswerToEverything
. Исходный объект возвращается API, которым я не управляю. Это просто означает, что я не могу использовать решение, которое ссылается на конкретное свойство по имени.2. Я обновил свой ответ, чтобы приспособить его к произвольному имени ключа
3. Извините, нет, это все еще не совсем правильно. Любое имя свойства может быть произвольным, а не только свойство, содержащее массив. Так
objKey !== "age"
не будет работать в этом примере. Кроме того, возвращаемый объект должен сохранять исходное имя свойства. Если внимательно присмотреться ко второму объекту в моем примере, вы увидите результат, который я ожидаю.
Ответ №3:
это универсальная функция, которая может обслуживать то, что вам нужно, вызывайте функцию с именем объекта и свойства, которое вы хотите преобразовать.
function arrayToObject(object, property) {
if(object[property] amp;amp; Array.isArray(object[property])) {
object[property] = object[property][0];
}
return object;
}
// let data = {
// name: [
// {
// "firstName":"First ",
// "lastName":"Last"
// }
// ],
// age: 21
// }
// console.log(arrayToObject(data, 'name'));
// { name: { firstName: 'First ', lastName: 'Last' }, age: 21 }
Обновить:
в случае, если мы не знаем имя свойства, мы можем использовать эту версию.
function arrayToObject(object) {
for(let key in object){
if(Array.isArray(object[key])) {
object[key] = object[key][0];
}
}
return object;
}
Комментарии:
1. Если вы посмотрите на комментарий @orangesquare под моим ответом, мы не знаем имя ключа внутреннего объекта, поэтому эта функция не будет работать, потому что она зависит от знания имени внутренней опоры
2. @rantao, спасибо за это уведомление, я обновил свою функцию, добавив неизвестное имя свойства
Ответ №4:
let a = {
name: [
{
"firstName":"First ",
"lastName":"Last"
}
],
age: 21
}
a.name = a.name[0];