Лучший способ заменить массив его содержимым внутри объекта

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