реструктурировать объект в 2D-объект массива - PullRequest
0 голосов
/ 26 сентября 2019

Я хотел бы реструктурировать объект боли в объект 2D-массива.

Изначально у меня есть что-то вроде:

{ 
   "education_histories.0.school":[ 
      "The education_histories.0.school field is required."
   ],
   "education_histories.0.degree":[ 
      "The education_histories.0.degree field is required."
   ],
   "education_histories.1.school":[ 
      "The education_histories.1.school field is required."
   ],
   "education_histories.1.degree":[ 
      "The education_histories.1.degree field is required."
   ],
}

Я хотел бы реструктурировать его так:

[ 
   { 
      "school":[ 
         "The education_histories.0.school field is required."
      ],
      "degree":[ 
         "The education_histories.0.degree field is required."
      ]
   },
   { 
      "school":[ 
         "The education_histories.1.school field is required."
      ],
      "degree":[ 
         "The education_histories.1.degree field is required."
      ]
   }
]

В настоящее время я пытаюсь сделать что-то вроде:

let validationErrors = []    

$.each(this.errors, (key, value) => {
  let splitKey = key.split('.')

  validationErrors[splitKey[1]] = { [splitKey[2]]: value }
})

Конечно, это не сработает, потому что оно переопределяет до последнего раунда.Вывод будет выглядеть так:

    [ 
       {
          "degree":[ 
             "The education_histories.0.degree field is required."
          ]
       },
       {
          "degree":[ 
             "The education_histories.1.degree field is required."
          ]
       }
    ]

Я бы хотел сделать что-то вроде

let validationErrors = []    

$.each(this.errors, (key, value) => {
  let splitKey = key.split('.')

  validationErrors[splitKey[1]][splitKey[2]] = value
})

Но это тоже не сработает.Там написано "TypeError: Cannot set property 'school' of undefined"

Любая помощь будет очень признательна.

Ответы [ 3 ]

2 голосов
/ 26 сентября 2019

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

  let validationErrors = []    

 for(const [key, value] of Object.entries(this.errors)) {
    let [ , index, name] = key.split('.');

    if(!validationErrors[index]) valudationErrors[index] = {};
    validationErrors[index][name] = value;
}
0 голосов
/ 26 сентября 2019

Object.entries и Array.reduce хороши для подобных вещей.

Предлагаемое решение здесь, слишком подробное объяснение ниже.

const input = {
  "education_histories.0.school": [
    "The education_histories.0.school field is required."
  ],
  "education_histories.0.degree": [
    "The education_histories.0.degree field is required."
  ],
  "education_histories.1.school": [
    "The education_histories.1.school field is required."
  ],
  "education_histories.1.degree": [
    "The education_histories.1.degree field is required."
  ],
}

// iterate over each key/value in the input object
// to build up the output.
const result = Object.entries(input).reduce((acc, [key, value]) => {

  // split the key into parts
  // e.g. ['educaton_histories', '0', 'school']
  const [section, index, field] = key.split('.');

  // use the index to bin the message in the right slot
  // e.g. result.0 = { ... }
  acc[index] = {

    // keep anything that already exists in this bin
    ...(acc[index] || {}),

    // add the message under the field's name
    // e.g. school: [ ... ]
    [field]: value
  }

  // return the updated object
  return acc;
}, {})

// the object's values are in the format you're after.
// we don't need the keys (the indices)
console.log(Object.values(result));

Object.entries(input) возвращает массив пар поле / значение.Итак:

const input = {
  'education_histories.0.school': 'school 0',
  'education_histories.0.degree': 'degree 0',
  'education_histories.1.school': 'school 1',
  'education_histories.1.degree': 'degree 1',
};

Object.entries(input);

Возвращает этот массив массивов:

[
  ["education_histories.0.school", "school 0"],
  ["education_histories.0.degree", "degree 0"],
  ["education_histories.1.school", "school 1"],
  ["education_histories.1.degree", "degree 1"],
]

Вызов reduce для этого массива вызывает вашу функцию обратного вызова для каждого элемента в массиве, передавая результат предыдущей итерации.и текущая запись массива:

// reduce takes two args: a callback function and an initial value
Object.entries(input).reduce(callback, {})

// the callback function takes:
// 1) the result from the previous iteration, and
// 2) and the current array item:
function callback(result, currentItem) {
  // on the first iteration:
  // previousResult = {}
  // currentItem[0] === "education_histories.0.school"
  // currentItem[1] === "school 0"

  // incorporate the item into the result:

  // break the key on '.', and capture the three entries:
  // section === 'eduction_histories'
  // index === 0
  // field === 'school 0'
  const [section, index, field] = currentItem[0].split('.');

  // result.0
  result[index] = {
    // if result.0 already exists, keep what's there
    ...(result[index] || {}),

    // add the current item
    // school: 'school 0'
    [field]: currentItem[1]
  }

  // return the updated result.
  // this will be passed in for the next iteration,
  // and will be the final return value when reduce exits
  return result;
}

Обратный вызов может быть встроенным, давая вам пример выше.

Object.entries(input).reduce((acc, [key, value]) => {
  // ...
}
0 голосов
/ 26 сентября 2019

Давайте попробуем, я думаю, это не лучшее решение:

const input = {
  "education_histories.0.school": [
    "The education_histories.0.school field is required."
  ],
  "education_histories.0.degree": [
    "The education_histories.0.degree field is required."
  ],
  "education_histories.1.school": [
    "The education_histories.1.school field is required."
  ],
  "education_histories.1.degree": [
    "The education_histories.1.degree field is required."
  ],
};

const raw = Object
  .keys(input) // ["education_histories.0.school", "education_histories.0.degree"]
  .reduce((pre, curr) => {
    const splittedStr = curr.split('.');
    const dataKey = splittedStr.pop(); // school
    const key = splittedStr.join('.'); // education_histories.0
    if (!pre[key]) {
      pre[key] = {};
    }
    pre[key][dataKey] = input[curr];
    return pre;
  }, {});

console.log(raw);

// {
//   "education_histories.0": {
//     "school": [
//       "The education_histories.0.school field is required."
//     ],
//       "degree": [
//         "The education_histories.0.degree field is required."
//       ]
//   },
//   "education_histories.1": {
//     "school": [
//       "The education_histories.1.school field is required."
//     ],
//       "degree": [
//         "The education_histories.1.degree field is required."
//       ]
//   }
// }

const output = Object.keys(raw).map((key) => raw[key]);

console.log(output);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...