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]) => {
// ...
}