Modify array of objects to replace with additional properties if null - javascript

I have an array of object as follows
let data = [
{
vertical_name: "CORE",
projects: [
{
name: "Alpha",
id: 187,
current_result: null,
}
]
},
{
vertical_name: "release",
projects: [
{
name: "Beta",
id: 27,
current_result: {
success_percentage: 37,
failure_percentage: 25,
skip_percentage: 36
}
},
{
name: "Charlie",
id: 47,
current_result: {
success_percentage: 37,
failure_percentage: 25,
skip_percentage: 36
}
}
]
}
]
As you can see current_result is null at one place. So i have to modify data to show that current_result is not tested. So in this case, instead of showing null, i want to show as follows. not_tested is 100 and skip, failure and success percentage is 0 in this case.
current_result: {
success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
}
Also on other values of current_result, since it is not null and has success, failure and skip values, not_tested should be 0 for this.
The final result should look something like this. can someone please let me know how to achieve this as it is slightly complicated for me to come to a definitive answer
result = [
{
vertical_name: "CORE",
projects: [
{
name: "Alpha",
id: 187,
current_result: {
success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
}
}
]
},
{
vertical_name: "release",
projects: [
{
name: "Beta",
id: 27,
current_result: {
success_percentage: 37,
failure_percentage: 25,
skip_percentage: 36,
not_tested: 0
}
},
{
name: "Charlie",
id: 47,
current_result: {
success_percentage: 37,
failure_percentage: 25,
skip_percentage: 36,
not_tested: 0
}
}
]
}
]

You could loop into data's projects array and insert keys you want in this way:
let data = [ { vertical_name: "CORE", projects: [ { name: "Alpha", id: 187, current_result: null, } ] }, { vertical_name: "release", projects: [ { name: "Beta", id: 27, current_result: { success_percentage: 37, failure_percentage: 25, skip_percentage: 36 } }, { name: "Charlie", id: 47, current_result: { success_percentage: 37, failure_percentage: 25, skip_percentage: 36 } } ] } ]
data.forEach(dat => {
dat.projects.forEach(prj => {
if (!prj.current_result) {
prj.current_result = {
success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
};
}
else {
prj.current_result.not_tested = 0;
}
})
})
console.log(data)

Using Array#map without mutating the original data
const data = [{"vertical_name":"CORE","projects":[{"name":"Alpha","id":187,"current_result":null}]},{"vertical_name":"release","projects":[{"name":"Beta","id":27,"current_result":{"success_percentage":37,"failure_percentage":25,"skip_percentage":36}},{"name":"Charlie","id":47,"current_result":{"success_percentage":37,"failure_percentage":25,"skip_percentage":36}}]}];
const formatted = data.map(item => Object.assign(item, {
projects: item.projects.map(project => {
if (project.current_result === null) {
project.current_result = {
success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
};
} else project.current_result.not_tested = 0;
return project;
})
}));
console.log(formatted);

let data = [{vertical_name: "CORE",projects: [{name: "Alpha",id: 187, current_result: null,}]},{vertical_name: "release", projects: [{ name: "Beta", id: 27, current_result: { success_percentage: 37, failure_percentage: 25, skip_percentage: 36}},{name: "Charlie", id: 47, current_result: { success_percentage: 37, failure_percentage: 25, skip_percentage: 36}}]}]
const newData = data.map((element)=>{
return element.projects.map((project)=>{
if(project.current_result === null){
return {...project, current_result: {success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
}
}
}
return {...project, current_result: {...project.current_result, not_tested: 0} }
})
})
console.log(newData)
you can try this code :
data.map((element)=>{
element.projects.map((project)=>{
if(project.current_result === null){
return {...project, current_result: {success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100
}
}
}
return {...project, current_result: {...project.current_result, not_tested: 0} }
})
})

You can filter out your result data and assign a default value.
const result = data.map((item) => {
const projects = item.projects.map((project) => {
if (!project?.current_result) {
return {
...project,
current_result: {
success_percentage: 0,
failure_percentage: 0,
skip_percentage: 0,
not_tested: 100,
},
};
} else {
return project;
}
});
console.log(result)

Related

Replace value in table based on another table

Is there a best practice in using arquero to reformat a value based on a set of ranges?
For example, I have the following 2 arrays:
const agefmt = [
{
'fmtname': 'agefmt',
'type' : 'n',
'format': [
{'start': 0, 'end': 10, 'label': '0 - 10'},
{'start': 11, 'end': 20, 'label': '11 - 20'},
{'start': 21, 'end': 30, 'label': '21 - 30'},
{'start': 31, 'end': 40, 'label': '31 - 40'},
{'start': 41, 'end': 50, 'label': '41 - 50'},
{'start': 51, 'end': 1000, 'label': '>51'}
]
},
]
const age = [
{ "AGE": 19 },
{ "AGE": 20 },
{ "AGE": 31 },
{ "AGE": 26 },
{ "AGE": 46 },
{ "AGE": 27 }
]
and I would like to replace the 'age' array with the 'label' within the range of the 'start' and 'end' values defined in the agefmt array.
The resulting array should look like the following:
[
{ "AGE": '0 - 10' },
{ "AGE": '11 - 20' },
{ "AGE": '31 - 40' },
{ "AGE": '21 - 30' },
{ "AGE": '41 - 60' },
{ "AGE": '21 - 30' }
]
I started writing it as a function like so, but found I couldn't pass the 'agefmt' as a parameter:
addFunction(function fmt({infmt, value}) {
console.log(value, infmt)
// calculate ranges here
return value
});
r.derive({rowvar : d => op.fmt(rowgrp, d.rowvar)})
Is there a more obvious way to achieve this?
It is just a matter of iterating through the age array, and then checking the nested AGE property against agefmt[0].format in a for loop. Whenever the AGE value is between the start and end values, then a label is considered found and we break out of the for loop.
One thing is that your expected output is incorrect based on your provided data: the first entry has an age of 19 and the matching label should be 11 - 20 not 0 - 10 as you wanted.
See proof-of-concept below:
const agefmt = [
{
fmtname: "agefmt",
type: "n",
format: [
{ start: 0, end: 10, label: "0 - 10" },
{ start: 11, end: 20, label: "11 - 20" },
{ start: 21, end: 30, label: "21 - 30" },
{ start: 31, end: 40, label: "31 - 40" },
{ start: 41, end: 50, label: "41 - 50" },
{ start: 51, end: 1000, label: ">51" },
],
},
];
const age = [
{ AGE: 19 },
{ AGE: 20 },
{ AGE: 31 },
{ AGE: 26 },
{ AGE: 46 },
{ AGE: 27 },
];
function addLabelToAge(age, labelFormat) {
return age.map(entry => {
let matchedLabel = '';
for (const format of labelFormat) {
if (entry.AGE >= format.start && entry.AGE <= format.end) {
matchedLabel = format.label;
break;
}
}
return { AGE: matchedLabel };
});
}
console.log(addLabelToAge(age, agefmt[0].format));
If you're comfortable with ES6 syntax, you can make the function a little more concise using object destructuring + object property assignment shorthand:
function addLabelToAge(age, labelFormat) {
return age.map(({ AGE }) => {
let matchedLabel = '';
for (const { start, end, label } of labelFormat) {
if (AGE >= start && AGE <= end) {
matchedLabel = label;
break;
}
}
return { AGE: matchedLabel };
});
}

Formatt array of obj

i have this array of obj
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
What I would like to get is an array of objects formatted like this
[
{
name: "Sistolica",
data: [130,135],
},
{
name: "Diastolica",
data: [72,75]
},
{
name: "Pulsazione",
data: [69,71],
},
],
For use within apex charts
The solution I found is not suitable and above all it is not reusable, if I passed an array that does not have the same keys that I indicated in my helper function, everything would be for the worse.
Can anyone help me with this?
I post the solution I had adopted, but I know it's really awful
export const setupGraphSeries = (data) => {
const sistolica = [];
const diastolica = [];
const pulsazione = [];
const formatter = data.map((item) => {
sistolica.push(item["sistolica"]);
diastolica.push(item["diastolica"]);
pulsazione.push(item["pulsazione"]);
return [
{ name: "Sistolica", data: sistolica },
{ name: "Diastolica", data: diastolica },
{ name: "Pulsazione", data: pulsazione },
];
});
return formatter;
};
One way is to just map over an array of the required properties. This does mean mapping over pressures once per item:
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
const params = ["diastolica","pulsazione","sistolica"];
const result = params.map( name => ({
name,
data: pressure.map(x => x[name])
}));
console.log(result);
Another way is to reduce the original keeping track of whether you have that item yet. This doesnt require multiple passes over the original data but is a little more complex:
const pressure = [
{
date: "2021-11-03T23:51:55.875Z",
diastolica: 72,
pulsazione: 69,
sistolica: 130,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "6183209bf91a7ed54a76c05e",
},
{
date: "2021-11-03T23:52:09.684Z",
diastolica: 75,
pulsazione: 71,
sistolica: 135,
user: "61830313ba36bf2504df0ec3",
__v: 0,
_id: "618320a9f91a7ed54a76c061",
},
];
const params = ["diastolica","pulsazione","sistolica"];
const result = Object.values(pressure.reduce( (a,item) => {
for(var i=0;i<params.length;i++){
const name = params[i];
a[name] = a[name] || {name,data:[]}
a[name].data.push(item[name]);
}
return a;
},{}));
console.log(result);

How to merge duplicate array?

const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
output: user 10,12 and 15 liked on your story ID 25
I want to show output like above. How to merge and show those like the output. Any idea?
You need to create a hash map, check the code snippet below:
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = {};
for (let data of allData) {
if (data.story in hash) hash[data.story] = [...hash[data.story], { ...data }];
else hash[data.story] = [{ ...data }];
}
console.log(hash);
You should use Map, which is what I would suggest. The code below does the same thing but using Maps.
const allData = [
{ name: 'John', story: 1 },
{ name: 'Ross', story: 2 },
{ name: 'Taylor', story: 1 },
{ name: 'Jimmy', story: 2 },
{ name: 'Amanda', story: 3 },
];
const hash = new Map();
for(let data of allData) {
const currentVal = hash.get(data.story);
if (currentVal) hash.set(data.story, [...currentVal, {...data}])
else hash.set(data.story, [{...data}])
}
console.log(hash);
I cann't comment. So i write here!
Are you wanting ...
result = [
{
story_id : 25,
user_id : [10, 12, 15]
}
]
Right?
This is solution of me
const data =
[{notification_id: 124, user_id: 10, story_id: 25, string: "liked on your story" }
{notification_id: 125, user_id: 12, story_id: 25, string: "liked on your story" }
{notification_id: 126, user_id: 15, story_id: 25, string: "liked on your story" }]
var result = data.reduce((res, item) => {
let storyID = item.story_id;
if (typeof res[storyID] == 'undefined') {
res[storyID] = {
story_id: storyID,
user_id: []
}
}
res[storyID].user_id.push(item.user_id);
return res;
}, []);
result = Object.values(result);

Get Specific Key with Highest Value from a (JSON) Object

I'm getting data back from an API response and attempting to get the name of the pitch with the highest speed. Here is a sample of the API response.
{
page: 1,
total_pages: 4,
listings: [
{
name: "A.J. Burnett",
pitches: [
{
name: "4 Seam FB",
speed: 96,
control: 84,
},
{
name: "Knuckle Curve",
speed: 79,
control: 74,
},
{
name: "Sinker",
speed: 95,
control: 64,
},
{
name: "Changeup",
speed: 81,
control: 44,
}
]
},
{
name: "Joe Smitch",
pitches: [
{
name: "4 Seam FB",
speed: 91,
control: 82,
},
{
name: "Changeup",
speed: 69,
control: 44,
}
]
},
]
}
Here is what I've tried:
itemSet.forEach( (item) => {
let fastestPitch = Object.keys(item.pitches).reduce((a, b) => {
item.pitches[a] > item.pitches[b] ? item.pitches[a].name : item.pitches[b].name
});
});
However, this always returns the name of the LAST pitch in the array. I'm attempting to return the pitch with the highest speed.
Edit: I've also tried the following, but it returns an error.
itemSet.forEach( (item) => {
let fastestPitch = Object.keys(item.pitches).reduce((a, b) => {
item.pitches[a].speed > item.pitches[b].speed ? item.pitches[a].name : item.pitches[b].name
});
});
Error:
(node:80698) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'speed' of undefined
You can do something like this:
const data = {
page: 1,
total_pages: 4,
listings: [{
name: "A.J. Burnett",
pitches: [{
name: "4 Seam FB",
speed: 96,
control: 84,
},
{
name: "Knuckle Curve",
speed: 79,
control: 74,
},
{
name: "Sinker",
speed: 95,
control: 64,
},
{
name: "Changeup",
speed: 81,
control: 44,
}
]
},
{
name: "Joe Smitch",
pitches: [{
name: "4 Seam FB",
speed: 91,
control: 82,
},
{
name: "Changeup",
speed: 69,
control: 44,
}
]
},
]
}
const fastesPitches = data.listings.map(({ pitches }) => {
return pitches.reduce((a, c) => c.speed > a.speed ? c : a).name;
});
console.log(fastesPitches);
To extract the fastest of each, you can Array#map each of the entries in listings and then Array#reduce their entries in pitches like this:
let data = { page: 1, total_pages: 4, listings: [{ name: "A.J. Burnett", pitches: [{ name: "4 Seam FB", speed: 96, control: 84, }, { name: "Knuckle Curve", speed: 79, control: 74, }, { name: "Sinker", speed: 95, control: 64, }, { name: "Changeup", speed: 81, control: 44, } ] }, { name: "Joe Smitch", pitches: [{ name: "4 Seam FB", speed: 91, control: 82, }, { name: "Changeup", speed: 69, control: 44, } ] }, ] };
let fastestPitches = data.listings.map(obj => {
return obj.pitches.reduce((best, current) => {
return best.speed > current.speed ? best : current
}, {}).name
});
console.log(fastestPitches)
Note that when you reduce, the first argument (best, in this case) is the result of the previous callback. So if you return just the name, you won't know what the speed of it was. So, you traverse and compare the speeds, then return the entire object that was better. When this finishes, you get the name of the result.
You could take a complete dynamic approach which looks for any depth and return the object with the wanted highest property from the most nested objects.
function getHighest(object, key) {
return Object.values(object).reduce((r, o) => {
if (!o || typeof o !== 'object') return r;
if (key in o && (!r || r[key] < o[key])) return o;
var temp = getHighest(o, key);
if (temp && (!r || r[key] < temp[key])) return temp;
return r;
}, undefined);
}
var data = { page: 1, total_pages: 4, listings: [{ name: "A.J. Burnett", pitches: [{ name: "4 Seam FB", speed: 96, control: 84 }, { name: "Knuckle Curve", speed: 79, control: 74 }, { name: "Sinker", speed: 95, control: 64 }, { name: "Changeup", speed: 81, control: 44 }] }, { name: "Joe Smitch", pitches: [{ name: "4 Seam FB", speed: 91, control: 82 }, { name: "Changeup", speed: 69, control: 44 }] }] },
highest = getHighest(data, 'speed');
console.log(highest.name);
console.log(highest);

Group and merge in nested object using Lodash

I have an object data as follows:
[
{
name: "Green Tea Brownie",
price: 60,
amount: 10,
seller: {
seller_id: 124,
seller_name: "Merry Shop"
}
},
{
name: "Cocoa Chiffon",
price: 20,
amount: 50,
seller: {
seller_id: 124,
seller_name: "Merry Shop"
}
},
{
name: "Milky Donut",
price: 40,
amount: 100
seller: {
seller_id: 421,
seller_name: "Sweet Bakery"
}
}
]
So I want to group data by "seller_id" and merge top level data assigns to object name "orders", just look like as following:
[
{
seller_id: 124,
seller_name: "Merry Shop",
orders: [
{
name: "Green Tea Brownie",
price: 60,
amount: 10
},
{
name: "Cocoa Chiffon",
price: 20,
amount: 50
}
]
},
{
seller_id: 421,
seller_name: "Sweet Bakery",
orders: [
{
name: "Milky Donut",
price: 40,
amount: 100
}
]
}
]
I tried to solve this problem several hours ago. Can anyone solve this case?
Thank you
You can use _.groupBy() and then _.map() the groups to requested format:
const { flow, partialRight: pr, groupBy, map, first, omit } = _
const fn = flow(
pr(groupBy, 'seller.seller_id'),
pr(map, group => ({
...first(group).seller,
orders: map(group, pr(omit, 'seller'))
}))
)
const data = [{"name":"Green Tea Brownie","price":60,"amount":10,"seller":{"seller_id":124,"seller_name":"Merry Shop"}},{"name":"Cocoa Chiffon","price":20,"amount":50,"seller":{"seller_id":124,"seller_name":"Merry Shop"}},{"name":"Milky Donut","price":40,"amount":100,"seller":{"seller_id":421,"seller_name":"Sweet Bakery"}}]
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
If you like to do with plain JS you can use reduce
const data = [{"name":"Green Tea Brownie","price":60,"amount":10,"seller":{"seller_id":124,"seller_name":"Merry Shop"}},{"name":"Cocoa Chiffon","price":20,"amount":50,"seller":{"seller_id":124,"seller_name":"Merry Shop"}},{"name":"Milky Donut","price":40,"amount":100,"seller":{"seller_id":421,"seller_name":"Sweet Bakery"}}]
const output = data.reduce((op,{name,price,amount,seller})=>{
if(op[seller['seller_id']]){
op[seller['seller_id']]['orders'].push({name,price,amount})
}
else {
op[seller['seller_id']] = {
seller_name: seller.seller_name,
seller_id: seller.seller_id,
orders: [{name,price,amount}]
}
}
return op;
},{})
console.log(Object.values(output))
Here is a pure JS solution using reduce:
const orders = [{
name: "Green Tea Brownie",
price: 60,
amount: 10,
seller: {
seller_id: 124,
seller_name: "Merry Shop"
}
}, {
name: "Cocoa Chiffon",
price: 20,
amount: 50,
seller: {
seller_id: 124,
seller_name: "Merry Shop"
}
}, {
name: "Milky Donut",
price: 40,
amount: 100,
seller: {
seller_id: 421,
seller_name: "Sweet Bakery"
}
}];
const ordersBySeller = Object.values(orders.reduce((accum, { name, price, amount, seller: { seller_id, seller_name } }) => {
const sellerOrders = accum[seller_id] ? accum[seller_id].orders || [] : [];
accum[seller_id] = { seller_id, seller_name, orders: [...sellerOrders, { name, price, amount } ] };
return accum;
}, {}));
console.log(ordersBySeller);

Categories

Resources