Создание нового объекта путем замены имен свойств, найденных в другом объекте - PullRequest
3 голосов
/ 11 марта 2020

Так что есть множество вопросов, которые go касаются того, как l oop через объект и внести простое изменение в имя свойства, но я пытаюсь решить это немного сложнее и был бы весьма признателен за некоторые Помогите.

По сути, я хочу сделать объект подобным этому:

{
   home_number: '1234',
   customer: {
     name: {
       last_name: 'Smith',
     },
   },
};

превратиться в этот

{
   home_number: '1234',
   individual: {
     name: {
       lastName: 'Smith',
     },
   },
};

На данный момент моя функция выглядит следующим образом

function restructure(obj) {
  let newObj = {};
  const newKeys = {
    fed_tax_id: 'federalTaxId',
    company_structure: 'companyStructure',
    home_number: 'homeNumber',
    customer: 'individual',
    first_name: 'firstName',
    last_name: 'lastName',
  }
}
  for(let key in obj){
    if (typeof obj[key] === 'object') {
      restructure(obj[key])
    }
    if(Object.hasOwnProperty.call(newKeys, key)){
      let newProperty = newKeys[key]
      newObj[newProperty] = obj[key]
    }
    if(!Object.hasOwnProperty.call(newKeys, key)){
      newObj[key] = obj[key]
    }
return newObj;
  }

Одна вещь, с которой я сейчас борюсь, это удаление ключей, которые необходимо изменить (я создал объект newKeys как способ показать ключи, которые нужно изменить, и что их нужно поменять на). Т.е. в этом случае, когда клиент изменяется на индивидуальный, он также изменит 'last_name' на 'lastName'.

С моей функцией, какой она есть в данный момент, объект возвращается так же, как:

{ homeNumber: '1234' }

Спасибо :) Если это уже было задано, пожалуйста, дайте мне знать, но после поиска по всему месту я не смог найти вопрос, достаточно близкий к этому.

Ответы [ 5 ]

1 голос
/ 11 марта 2020

Вы можете использовать delete для удаления свойства из объекта.

Примечание: Моя функция изменит исходный объект. Если вы хотите скопировать объект, обязательно сделайте его глубокое копирование, используя JSON методы

const newKeys = {
    fed_tax_id: 'federalTaxId',
    company_structure: 'companyStructure',
    home_number: 'homeNumber',
    customer: 'individual',
    first_name: 'firstName',
    last_name: 'lastName',
}
const obj = {
   home_number: '1234',
   individual: {
     name: {
       lastName: 'Smith',
     },
   },
};
function restructure(obj){
  for(let k in obj){
    if(typeof obj[k] === "object" && !Array.isArray(obj[k])){
      restructure(obj[k]);
    }
    if(newKeys[k]){
      obj[newKeys[k]] = obj[k];
      delete obj[k];
    }
  }
}

restructure(obj);
console.log(obj)
1 голос
/ 11 марта 2020

Вам нужна только проверка собственного свойства и фактического объекта, чтобы предотвратить назначение не собственных свойств.

Для всех свойств вы можете сначала взять новый ключ или, если значения не существует, как по умолчанию фактический ключ.

Затем вам нужно присвоить либо результат рекурсивного вызова, либо, если не объект, просто значение.

function restructure(obj) {
    let newObj = {};
    const newKeys = { fed_tax_id: 'federalTaxId', company_structure: 'companyStructure', home_number: 'homeNumber', customer: 'individual', first_name: 'firstName', last_name: 'lastName' };

    for (let key in obj) {
        if (!obj.hasOwnProperty(key)) continue;
        newObj[newKeys[key] || key] = obj[key] && typeof obj[key] === 'object'
            ? restructure(obj[key])
            : obj[key];
    }
    return newObj;
}

console.log(restructure({ home_number: '1234', customer: { name: { last_name: 'Smith' } } }));
1 голос
/ 11 марта 2020

Поскольку restructure возвращает новый объект, вам нужно присвоить результат рекурсивного вызова restructure, иначе он будет go неиспользованным, что и происходит в вашем текущем коде.

Но вероятно, вместо этого было бы проще сопоставить массив записей - замените ключ в записи ассоциированным значением объекта , если объект имеет этот ключ, затем превратите записи обратно в объект с Object.fromEntries:

const newKeys = {
  fed_tax_id: 'federalTaxId',
  company_structure: 'companyStructure',
  home_number: 'homeNumber',
  customer: 'individual',
  first_name: 'firstName',
  last_name: 'lastName',
};
const restructure = obj => Object.fromEntries(
  Object.entries(obj).map(
    ([key, val]) => [
      newKeys[key] || key,
      typeof val === 'object' && val !== null ? restructure(val) : val
    ]
  )
);

console.log(restructure({
   home_number: '1234',
   customer: {
     name: {
       last_name: 'Smith',
     },
   },
}));

Имейте в виду, что typeof null дает object, поэтому вы захотите проверить null перед рекурсивной реструктуризацией (как это сделано в приведенном выше коде), иначе вы можете время от времени сталкиваться с ошибками.

0 голосов
/ 11 марта 2020

Я бы отделил метод преобразования ключей от кода, который применяет его к вашему объекту. В этом фрагменте мы напишем обобщенную функцию c rekey, которая принимает функцию преобразования ключей и возвращает функцию, которая принимает объект и рекурсивно запускает эту функцию над вашими клавишами.

Итак, если вы хотите чтобы преобразовать все ключи в виде змеи в ключи в верблюде, мы можем передать rekey простую функцию преобразования на основе регулярных выражений, например:

const rekey = (fn) => (obj) => 
  typeof obj == 'object'
    ? Object .fromEntries (
        Object .entries (obj) .map (([k, v]) => [fn(k), rekey (fn) (v)])
      )
    : obj


const snakeToCamel = (str) => 
  str .replace (/_([a-z])/g, (_, c) => c .toUpperCase ())

const obj = {home_number: '1234', customer: {name: {last_name: 'Smith'}}}

console .log (
  rekey (snakeToCamel) (obj)
)

Если вы работаете в среде без Object .fromEntries, ее легко заменить. Вы можете использовать любую из следующих версий:

// more elegant
const fromEntries = (pairs) => 
  pairs .reduce ((a, [k, v]) => ({... a, [k]: v}), {})

// more memory-efficient
const fromEntries = (pairs) => 
  pairs .reduce ((a, [k, v]) => {a[k] = v; return a}, {})

Но смысл этого разделения в том, что теперь это функция многократного использования, и если вы хотите изменить способ преобразования отдельных клавиш, скажем, из поиска, мы может просто передать rekey другую функцию:

const rekey = (fn) => (obj) => 
  typeof obj == 'object'
    ? Object .fromEntries (
        Object .entries (obj) .map (([k, v]) => [fn(k), rekey(fn)(v)])
      )
    : obj

const newKeys = {
    fed_tax_id: 'federalTaxId',
    company_structure: 'companyStructure',
    home_number: 'homeNumber',
    customer: 'individual',
    first_name: 'firstName',
    last_name: 'lastName',
}

const obj = {home_number: '1234', customer: {name: {last_name: 'Smith'}}}

console .log (
  rekey (key => newKeys[key] || key) (obj)
)

Конечно, с помощью этой функции карри вы можете сохранить ссылку, скажем, rekey (snakeToCamel) и повторно использовать ее для множества различных объектов.

0 голосов
/ 11 марта 2020

Вы можете использовать Object.entries и Object.fromEntries. Кроме того, создать объект newKeys можно только один раз, создавая его каждый раз, когда вызывается функция.

const newKeys = {
	fed_tax_id: 'federalTaxId',
	company_structure: 'companyStructure',
	home_number: 'homeNumber',
	customer: 'individual',
	first_name: 'firstName',
	last_name: 'lastName',
}
function restructure(obj) {

	let entries = Object.entries(obj).map(([key, val]) => {
		val = typeof val === 'object' && !Array.isArray(val) ? restructure(val) : val
		return [newKeys[key] || key, val]
	});

	return Object.fromEntries(entries)

}

console.log(restructure({
	home_number: '1234',
	customer: {
		name: {
			last_name: 'Smith',
		},
	},
}))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...