I am trying to find the reactive way of manipulating data in an array of objects. In the array below, I want to determine the low score in groups of four and add a low and diff property to the item.
arr = [
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
];
arr$: Observable<Arr[]> = of(this.arr);
getData() {
const scores = this.arr$.pipe(
map((result) =>
result.map((data) => {
return {
x: data.score,
};
})
)
// reduce((acc, x) => (acc = acc > x.score ? acc :x.score), 0)
);
return scores;
}
}
/*
Desired result
arr = [
{ name: 'Cliff', score: 44, low: 44, diff 0 },
{ name: 'Bob', score: 55, low: 44, diff: 9 },
{ name: 'Jack', score: 404, low 44, diff: 360 },
{ name: 'John', score: 50, low: 44, diff: 6 },
{ name: 'Doug', score: 22, low 5, diff: 17 },
{ name: 'EZ', score: 550, low 5, diff: 545 },
{ name: 'Bill', score: 404, low 5, diff: 399 },
{ name: 'Dan', score: 5, low 5, diff: 0 },
{ name: 'Rich', score: 404, low: 404, diff: 0 },
{ name: 'Steve', score: 565. low 404, diff: 121 },
];
*/
I can't seem to get past the few lines of code that I've written. A StackBlitz is here.
CodePudding user response:
This could be a reactive way to get what you want. The comments in the code explain the logic.
// the from rxjs function takes an array and returns an
// Observable that emits each item in the array
from(arr)
.pipe(
// bufferCount will emit an array of arrays of items,
// therefore creates the groups of four items
bufferCount(4),
// for each group we find the low and create
// the new items with the low value and the diff
map((buff) => {
const low = buff.reduce((acc, curr) => {
return acc < curr.score ? acc : curr.score;
}, Infinity);
return buff.map((v) => ({ ...v, low, diff: v.score - low }));
}),
// with mergeMap we flatten the groups of items
// and emit each item
mergeMap((buffEnriched) => buffEnriched),
// if you want to emit an array rather than each single
// object you add toArray
toArray()
)
CodePudding user response:
it makes more sense to sort, then generate your data. otherwise, your output data in your question makes little sense to me.
// DATA IN
arr = [
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
];
// PROCESSING and OUTPUT
let lowest = arr[0].score;
let output_arr = arr.sort((a, b)=>{
if(a.score < b.score) return -1;
if(a.score > b.score) return 1;
return 0;
}).map((a)=>{
if(a.score < lowest) lowest = a.score;
return {
name: 'Steve',
score: 565,
low: lowest,
diff: a.score - lowest
};
});
// use output array output
console.log(output_arr);
Example
INPUT
[
{ name: 'Cliff', score: 44 },
{ name: 'Bob', score: 55 },
{ name: 'Jack', score: 404 },
{ name: 'John', score: 50 },
{ name: 'Doug', score: 22 },
{ name: 'EZ', score: 550 },
{ name: 'Bill', score: 404 },
{ name: 'Dan', score: 5 },
{ name: 'Rich', score: 404 },
{ name: 'Steve', score: 565 },
]
OUTPUT
[{
diff: 0,
low: 5,
name: "Steve",
score: 565
}, {
diff: 17,
low: 5,
name: "Steve",
score: 565
}, {
diff: 39,
low: 5,
name: "Steve",
score: 565
}, {
diff: 45,
low: 5,
name: "Steve",
score: 565
}, {
diff: 50,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 399,
low: 5,
name: "Steve",
score: 565
}, {
diff: 545,
low: 5,
name: "Steve",
score: 565
}, {
diff: 560,
low: 5,
name: "Steve",
score: 565
}]