Массив объектов для накопления всех свойств объекта, для которых другое свойство одинаково

77
8

Пусть говорят, что мой массив объектов выглядит так:

array1 = [
{
rule: {
column: "colName",
value: "val1"
}
},
{
rule: {
column: "colName",
value: "val2"
}
},
{
rule: {
column: "colName",
value: "val3"
}
},
{
rule: {
column: "colName2",
value: "val4"
}
}
]

Я хочу написать что-то вроде операции reduce которая проверяет, равны ли rule.column для всех элементов массива, и если да, то rule.column значения одного из них при удалении остальных. Чтобы дать мне что-то вроде:

array2 = [
{
rule: {
column: "colName",
value: ["val1", "val2", "val3"]
}
},
{
rule: {
column: "colName2",
value: ["val4"]
}
}
]

Есть ли простой способ сделать это? Я могу определенно написать регулярную function чтобы сделать это, но я предполагаю, что я должен был бы сделать операцию reduce на array1 вместо этого?

Изменить: исходный вопрос имел otherProperty: {} свойства после rule но мой объект на самом деле не имеет этого (он на объекте верхнего уровня)

спросил(а) 2021-01-25T16:59:20+03:00 5 месяцев назад
1
Решение
89

Конечно, просто создайте объект с ключами, соответствующими каждому столбцу, нажмите на внутренний массив values и затем захватите значения объекта:

const input = [{
rule: {
column: "colName",
value: 'v1'
},
otherProperty: 'otherProp',
},
{
rule: {
column: "colName",
value: 'v2'
},
otherProperty: 'otherProp',
},
{
rule: {
column: "colName",
value: 'val3',
},
otherProperty: 'otherProp',
},
{
rule: {
column: "colName2",
value: 'val4'
},
otherProperty: 'otherProp',
}
];
const outputCols = input.reduce((outputCols, { rule: { column, value }, ...otherProps}) => {
if (!outputCols[column]) {
outputCols[column] = { rule: { column, value: [] }, ...otherProps };
}
outputCols[column].rule.value.push(value);
return outputCols;
}, {});
console.log(Object.values(outputCols));

Обратите внимание, что если otherProps отличаются в последующих объектах, они будут игнорироваться в настоящее время.

ответил(а) 2021-01-25T16:59:20+03:00 5 месяцев назад
63

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

Имя otherProperty выходит за рамки, но вы можете использовать либо функцию Object.assign либо синтаксис Spread.

let array1 = [    {          rule: {             column: "colName",             value: ["val1"]         },         otherProperty: {}    },    {          rule: {             column: "colName",             value: ["val2"]         },         otherProperty: {}    },    {          rule: {             column: "colName",             value: ["val3"]         },         otherProperty: {}    },    {          rule: {             column: "colName2",             value: ["val4"]         },         otherProperty: {}    }],
result = Object.values(array1.reduce((a, c) => {
(a[c.rule.column] || (a[c.rule.column] = {rule: {column: c.rule.column, value: []}, otherProperty: {}})).rule.value.push(...c.rule.value);
return a;
}, {}));

console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }

ответил(а) 2021-01-25T16:59:20+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема