У меня есть этот объект JSON и вы хотите группировать значения по типу.
var costs = [
{ 'name': 'JON', 'flight':100, 'value': 12, type: 'uns' },
{ 'name': 'JON', 'flight':100, 'value': 35, type: 'sch' },
{ 'name': 'BILL', 'flight':200, 'value': 33, type: 'uns' },
{ 'name': 'BILL', 'flight':200, 'value': 45, type: 'sch' }
];
Я хочу что-то вроде этого:
var costs = [
{ 'name': 'JON', 'flight':100, 'uns': 12, 'sch': 35 },
{ 'name': 'BILL', 'flight':200, 'uns': 33, 'sch': 45}
];
Я пытаюсь использовать lodash, но без успеха:
var compiled_costs = _.chain(costs)
.groupBy("flight")
.value();
{
"100":
[ {"name":"JON","flight":100,"value":12,"type":"uns"},
{"name":"JON","flight":100,"value":35,"type":"sch"}
],
"200":
[
{"name":"BILL","flight":200,"value":33,"type":"uns"},
{"name":"BILL","flight":200,"value":45,"type":"sch"}
]
}
var res = _.chain(costs)
.groupBy('flight') // group costs by flight
.mapValues(function(flightItems, flight) { // iterate flight arrays
return { // return obj on each flight array
name: _.get(flightItems, [0, 'name']), // just get name from first item of flight array
flight: flight,
uns: _.chain(flightItems) // get all flight items with type uns and sum items values
.filter({type: 'uns'})
.sumBy('value')
.value(),
sch: _.chain(flightItems)
.filter({type: 'sch'})
.sumBy('value')
.value()
}
})
.values() // get values from object
.value();
Для этого была создана карта. Поскольку вы объединяете данные, вы можете захотеть сохранить хэш-карту для более быстрого поиска. В противном случае превращение его в массив тривиально, как я демонстрирую.
function compiled_costs(costs) {
var hash = new Map();
for (let cost of costs) {
if (hash.has(cost.name)) {
var values = hash.get(cost.name),
value = values.value,
type = values.type;
delete values.value;
delete values.type;
values.uns = value;
values.sch = cost.value;
} else hash.set(cost.name, cost)
}
return hash
}
var costs = [{
'name': 'JON',
'flight': 100,
'value': 12,
type: 'uns'
},
{
'name': 'JON',
'flight': 100,
'value': 35,
type: 'sch'
},
{
'name': 'BILL',
'flight': 200,
'value': 33,
type: 'uns'
},
{
'name': 'BILL',
'flight': 200,
'value': 45,
type: 'sch'
}
];
var formated = [...compiled_costs(costs).values()];
//formated
console.log('formated',formated);
//hashed
var hashed = [...compiled_costs(costs)];
console.log('hashed',hashed);
Вы можете использовать закрытие над хэш-таблицей для тех же именованных объектов.
var data = [{ name: 'JON', flight: 100, value: 12, type: 'uns' }, { name: 'JON', flight: 100, value: 35, type: 'sch' }, { name: 'BILL', flight: 200, value: 33, type: 'uns' }, { name: 'BILL', flight: 200, value: 45, type: 'sch' }],
grouped = data.reduce(function (hash) {
return function (r, o) {
if (!hash[o.name]) {
hash[o.name] = { name: o.name, flight: o.flight };
r.push(hash[o.name]);
}
hash[o.name][o.type] = (hash[o.name][o.type] || 0) + o.value;
return r;
}
}(Object.create(null)), []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Вы можете использовать собственный метод reduce()
:
const costs = [
{ 'name': 'JON', 'flight':100, 'value': 12, type: 'uns' },
{ 'name': 'JON', 'flight':100, 'value': 35, type: 'sch' },
{ 'name': 'BILL', 'flight':200, 'value': 33, type: 'uns' },
{ 'name': 'BILL', 'flight':200, 'value': 45, type: 'sch' }
];
const compiledCosts = costs.reduce((acc, { name, flight, value, type }) => {
let obj = acc.find(x => x.name === name);
if (typeof obj === 'undefined') {
acc.push({ name, flight, [type]: value });
} else {
obj[type] = value;
}
return acc;
}, []);
console.log(compiledCosts);