Find average value within different JSON objects - javascript

I have a JSON object which is as follows, it consists of an id, and object measurements.
Object measurements consists of Tastiness which has its respective taste for each level, such as level 25,50, and 100. I'm trying to combine the tastiness into 1 value with the average of each taste level (for example total of sourness / objectMeasurements number)
"objectId": "de8e783a-1a13-42be-b1b2-1bc7be24b511"
"objectMeasurements": [
{
"id": "f986cb0d-a9f2-4d8f-ad2f-9ff46e097764",
"data": {
"scale": 5,
"tastiness": [
{
"level": 100,
"sourness": 4,
"freshness": 5,
"sweetness": 3
},
{
"level": 25,
"sourness": 4,
"freshness": 3,
"sweetness": 5
},
{
"level": 50,
"sourness": 3,
"freshness": 5,
"sweetness": 5
}
]
},
},
{
"id": "12efc22b-ff69-4248-8b25-4ed8981089df",
"data": {
"scale": 5,
"tastiness": [
{
"level": 100,
"sourness": 3,
"freshness": 5,
"sweetness": 5
},
{
"level": 25,
"sourness": 5,
"freshness": 4,
"sweetness": 4
},
{
"level": 50,
"sourness": 4,
"freshness": 5,
"sweetness": 3
}
]
}
}
]
How is it possible for me to combine the data tastiness and get the average of each property, into 1 object measurement such as something like this
"objectId": "de8e783a-1a13-42be-b1b2-1bc7be24b511"
"objectMeasurements": [
{
"id": "someId",
"data": {
"scale": 5,
"tastiness": [
{
"level": 100,
"sourness": 3.5,
"freshness": 2,
"sweetness": 4
},
{
"level": 25,
"sourness": 4.5,
"freshness": 3.5,
"sweetness": 4.5
},
{
"level": 50,
"sourness": 3.5,
"freshness": 2,
"sweetness": 4
}
]
},
},

const input = {
"objectId": "de8e783a-1a13-42be-b1b2-1bc7be24b511",
"objectMeasurements": [{
"id": "f986cb0d-a9f2-4d8f-ad2f-9ff46e097764",
"data": {
"scale": 5,
"tastiness": [{
"level": 100,
"sourness": 4,
"freshness": 5,
"sweetness": 3
}, {
"level": 25,
"sourness": 4,
"freshness": 3,
"sweetness": 5
}, {
"level": 50,
"sourness": 3,
"freshness": 5,
"sweetness": 5
}]
},
}, {
"id": "12efc22b-ff69-4248-8b25-4ed8981089df",
"data": {
"scale": 5,
"tastiness": [{
"level": 100,
"sourness": 3,
"freshness": 5,
"sweetness": 5
}, {
"level": 25,
"sourness": 5,
"freshness": 4,
"sweetness": 4
}, {
"level": 50,
"sourness": 4,
"freshness": 5,
"sweetness": 3
}]
}
}]
}
let res = {}
input.objectMeasurements.map(obj => {
obj.data.tastiness.map((m) => {
const keys = Object.keys(m);
keys.map(key => {
if (key !== 'level') {
if (!res[(m.level)].count[key]) {
res[(m.level)].count[key] = res[(m.level)].totals[key] = 0;
}
res[(m.level)].count[key]++;
res[(m.level)].totals[key] += m[key];
} else {
if (!res[(m.level)]) {
res[(m.level)] = {
count: {},
totals: {}
}
}
}
});
});
});
let tastiness = [];
Object.keys(res).reverse().map(levelKey => {
let avg = {};
avg.level = +levelKey;
Object.keys(res[levelKey].count).map(tasteKey => {
avg[tasteKey] = res[levelKey].totals[tasteKey] / res[levelKey].count[tasteKey];
});
tastiness.push(avg);
});
input.objectMeasurements = tastiness;
console.log(input);

Related

Javascript creates new arrays based on conditions

I have old and entity arrays:
var old = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 100,
"yield": 20,
"worth": 30
},
{
"id": 4,
"entity_type_id": 1,
"product_id": 4,
"name": "test2",
"acreage": 10,
"yield": 20,
"worth": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40
}
]
var entity = [
{"id": 1, "name": "a1"},
{"id": 2, "name": "a2"},
{"id": 3, "name": "a3"}
]
I hope to get the following data:
var newArr = [
{
"id": 3,
"entity_type_id": 1,
"product_id": 4,
"name": "test1",
"acreage": 110,
"yield": 40,
"worth": 30,
"entity_type_1": 2, // The total amount of entity_type_id (entity_type_id: 1)
"entity_type_2": 0,
"entity_type_3": 0
},
{
"id": 5,
"entity_type_id": 3,
"product_id": 5,
"name": "test3",
"acreage": 20,
"yield": 20,
"worth": 40,
"entity_type_1": 0,
"entity_type_2": 0,
"entity_type_3": 1 // The total amount of entity_type_id (entity_type_id: 3)
}
]
console.log(newArr)
I tried the following code and got some data. I'm not sure if there will be any exceptions or errors.
What's more, I don't know how to deal with the entity array data. Can someone help me solve this problem and get the result I expect?
Thank you very much !
function mergeArr(arr) {
const temp = []
arr.forEach((dataItem) => {
if (temp.length) {
let filterValue = temp.filter((items) => {
return items.product_id === dataItem.product_id
})
if (filterValue.length) {
temp.forEach((n) => {
if (n.product_id === filterValue[0].product_id) {
n.yield = dataItem.yield + filterValue[0].yield
n.acreage = dataItem.acreage + filterValue[0].acreage
n.worth = dataItem.worth + filterValue[0].worth
}
})
} else {
temp.push(dataItem)
}
} else {
temp.push(dataItem)
}
})
return temp
}
Youi could find the object and sum the wanted properties. For entity take another loop and map new entries and build a new object from it for spreading.
var old = [{ id: 3, entity_type_id: 1, product_id: 4, name: "test1", acreage: 100, yield: 20, worth: 30 }, { id: 4, entity_type_id: 1, product_id: 4, name: "test2", acreage: 10, yield: 20, worth: 0 }, { id: 5, entity_type_id: 3, product_id: 5, name: "test3", acreage: 20, yield: 20, worth: 40 }],
entity = [{ id: 1, name: "a1" }, { id: 2, name: "a2" }, { id: 3, name: "a3" }],
entityTypes = Object.fromEntries(entity.map(({ id }) => ['entity_type_' + id, 0])),
result = old.reduce((r, o) => {
let temp = r.find(q => q.product_id === o.product_id);
if (!temp) r.push(temp = { ... o, ...entityTypes });
else ['acreage', 'yield', 'worth'].forEach(k => temp[k] += o[k]);
temp['entity_type_' + o.entity_type_id]++;
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Retrive Value from nested object using recursion

I have an JS object data, from this array of object, I need to take "amount" value which is inside of "limitBreakup" Array. I have done using .map(), But I am intersted to know the implementation of the same using Recursion.
var data = [
{
"limitRequirementId":"123",
"facilityType":"cc",
"amount":800000,
"existingRoi":12,
"existingPf":12100,
"repoRate":5,
"spread":10,
"tenure":24,
"margin":10000,
"loanVariable":{
"type":"roi/commission",
"value":15
},
"limitBreakup":[
{
"limitRequirementId":"13",
"facilityType":"cc",
"repoRate":5,
"amount":8000,
"spread":10,
"tenure":24,
"margin":100,
"loanVariable":{
"type":"roi/commission",
"value":15
}
},
{
"limitRequirementId":"22",
"facilityType":"LC",
"repoRate":4,
"amount":900,
"spread":6,
"tenure":21,
"margin":15,
"loanVariable":{
"type":"roi/commission",
"value":10
}
}
]
},
{
"limitRequirementUniqueId":"13",
"limitRequirementId":"13",
"facilityType":"lc",
"amount":900000,
"existingRoi":10,
"existingPf":1000,
"repoRate":3,
"spread":1,
"tenure":21,
"margin":1000,
"loanVariable":{
"type":"roi/commission",
"value":15
},
"limitBreakup":[
{
"limitRequirementId":"35",
"facilityType":"CC",
"repoRate":6,
"amount":600,
"spread":8,
"tenure":28,
"margin":13,
"loanVariable":{
"type":"roi/commission",
"value":14
}
}
]
}
]
My Solution using normal iteration works:
data.forEach((d, i)=>{
let limitBreakup = d.limitBreakup;
if(Array.isArray(limitBreakup)){
limitBreakup.forEach((l)=>{ console.log(l, '->', l.amount) })
}else{
console.log(limitBreakup, 'else->', limitBreakup.amount)
}
//console.log(d.limitBreakup);
})
But using Recursion, I am half way:
https://jsfiddle.net/1g98sLw3/2/
http://www.mocky.io/v2/5ea974eb3400005e003f0203 (Since the json object is very big, I have pasted in mocky.io for reference)
Something like this should work
Demo proof: https://jsfiddle.net/do58kj3q/
You need a loop to pass through your objects and then add them to the array when you meet the criteria
var data = [{
"limitRequirementId": "123",
"facilityType": "cc",
"amount": 800000,
"existingRoi": 12,
"existingPf": 12100,
"repoRate": 5,
"spread": 10,
"tenure": 24,
"margin": 10000,
"loanVariable": {
"type": "roi/commission",
"value": 15
},
"limitBreakup": [{
"limitRequirementId": "13",
"facilityType": "cc",
"repoRate": 5,
"amount": 8000,
"spread": 10,
"tenure": 24,
"margin": 100,
"loanVariable": {
"type": "roi/commission",
"value": 15
}
},
{
"limitRequirementId": "22",
"facilityType": "LC",
"repoRate": 4,
"amount": 900,
"spread": 6,
"tenure": 21,
"margin": 15,
"loanVariable": {
"type": "roi/commission",
"value": 10
}
}
]
},
{
"limitRequirementUniqueId": "13",
"limitRequirementId": "13",
"facilityType": "lc",
"amount": 900000,
"existingRoi": 10,
"existingPf": 1000,
"repoRate": 3,
"spread": 1,
"tenure": 21,
"margin": 1000,
"loanVariable": {
"type": "roi/commission",
"value": 15
},
"limitBreakup": [{
"limitRequirementId": "35",
"facilityType": "CC",
"repoRate": 6,
"amount": 600,
"spread": 8,
"tenure": 28,
"margin": 13,
"loanVariable": {
"type": "roi/commission",
"value": 14
}
}]
}
]
var array=[];
function recursiveCounter(arr) {
for (let i = 0; i < arr.length; i++) {
const obj = arr[i];
if (!obj.limitBreakup) {
array.push(obj.amount);
}
if (Array.isArray(obj.limitBreakup)) {
recursiveCounter((obj.limitBreakup));
}
}
}
recursiveCounter(data);
console.log(array)

Formatting of JavaScript Objects, Showing Sub Products under Products

I have an array of objects for products I want to show objects that have a parent ID under their parent object with property called subproduct
I have a array object like
let products = [{
"id": 30,
"service_provider_id": 4,
"parent_id": null,
"status_id": 1,
"code": "1450",
"name": "Paypal"
},
{
"id": 31,
"service_provider_id": 4,
"parent_id": 30,
"status_id": 1,
"code": "1451",
"name": "Payments"
}
]
I want to format it in the following way
"products": [{
"id": 30,
"service_provider_id": 4,
"parent_id": null,
"status_id": 1,
"code": "14",
"name": "Paypal"
"sub-products": [{
"id": 31,
"service_provider_id": 4,
"parent_id": 30,
"status_id": 1,
"code": "15",
"name": "Paypal-Payments"
}]
}]
This will work
let products = [
{
"id": 30,
"service_provider_id": 4,
"parent_id": null,
"status_id": 1,
"code": "1450",
"name": "Paypal"
},
{
"id": 31,
"service_provider_id": 4,
"parent_id": 30,
"status_id": 1,
"code": "1451",
"name": "Payments"
}
]
let formated = [];
formated = products.filter(product => product.parent_id == null);
formated.forEach(formatedproduct=>{
products.forEach(product =>{
if(product.parent_id == formatedproduct.id){
if(!formatedproduct.sub_products )
{
formatedproduct.sub_products = [];
}
product.name = formatedproduct.name +' '+product.name;
formatedproduct.sub_products.push(product);
}
});
})
console.log(formated);
You can use a combination of map and reduce
const grouped = [
...products
.sort((a, b) => a.parent_id - b.parent_id)
.reduce((a, b) => a.set(b.parent_id || b.id, (a.get(b.parent_id) || []).concat(b)), new Map())
.values()
]
.map(([f, ...rest]) => (f.sub_products = rest, f));
console.log(grouped);
<script>
const products = [{
'id': 30,
'service_provider_id': 4,
'parent_id': null,
'status_id': 1,
'code': '1450',
'name': 'Paypal'
},
{
'id': 31,
'service_provider_id': 4,
'parent_id': 30,
'status_id': 1,
'code': '1451',
'name': 'Payments'
},
{
'id': 32,
'service_provider_id': 4,
'parent_id': null,
'status_id': 1,
'code': '1450',
'name': 'Paypal'
},
{
'id': 33,
'service_provider_id': 4,
'parent_id': 32,
'status_id': 1,
'code': '1451',
'name': 'Payments'
}
];
</script>

How do I manipulate the Javascript array?

I want to manipulate the array with sample data.
What I'm trying to do is find the movieId in the votes data, count it, get the user's name
Data Description:
movieId: votes have multiple movieIds, but only need to import one.
movieIdLength: total number of movieId's.
name: User name with the same movieId.
For example:
var votes = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
what I want:
var votesResult = [{
"movieId": 2,
"movieIdLength": 1,
"name": "James"
},{
"movieId": 1,
"movieIdLength": 1,
"name": "Dan"
},{
"movieId": 3,
"movieIdLength": 2,
"name": "Laura, Steve"
}]
ES6:
const a = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
const r = [...new Set(a.map(x => x.movieId))]
.map(x => Object.assign({movieId: x},
{movieIdLength: a.filter(l => l.movieId === x).length},
{name: a.filter(q => q.movieId === x).map(n => n.name).join(', ')}));
console.log(JSON.stringify(r, null, 2));
Less clear but without code duplication:
const a = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
const r = [...new Set(a.map(x => x.movieId))]
.map(x => Object.assign({movieId: x},
((f) => Object.assign({movieIdLength: f.length, name: f.map(({name}) => name).join(', ')})
)(a.filter(({movieId}) => movieId === x))
));
console.log(JSON.stringify(r, null, 2));
You need to start with an empty list for the result array, then you loop over the data and check if the movie id is in the result list. is it is, then count movieIdCount up by 1 and append the name to the name field, otherwise add a new movie to the result array, do you want the algorithm?

lodash merge and combine objects

I have an array of objects as below that I read from my database using sequelize ORM:
I want to have all my videos from a section, but the better I can return using sequelize is :
[{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": {
"id": 11,
"source": "sourrrccrsss22222",
"videoSubSection": 2
}
},
{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": {
"id": 12,
"source": "sourrrccrsss111",
"videoSubSection": 2
}
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": {
"id": 13,
"source": "sourrrcc",
"videoSubSection": 1
}
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": {
"id": 14,
"source": "sourrrcc",
"videoSubSection": 1
}
}]
Is there a way to merge and combine the objects in my array to obtain something like this :
[{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": [{
"id": 11,
"source": "sourrrccrsss22222",
"videoSubSection": 2
},{
"id": 12,
"source": "sourrrccrsss111",
"videoSubSection": 2
}]
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": [{
"id": 13,
"source": "sourrrcc",
"videoSubSection": 1
},{
"id": 14,
"source": "sourrrcc",
"videoSubSection": 1
}]
}
The function that approach the most is _.mergeWith(object, sources, customizer) but the main problem I have is that I have on object and need to merge this object.
In plain Javascript, you can use Array#forEach() with a temporary object for the arrays.
var data = [{ id: 2, name: "Ru", subsection: 1, Video: { id: 11, source: "sourrrccrsss22222", VideoSubSection: 2 } }, { id: 2, name: "Ru", subsection: 1, Video: { id: 12, source: "sourrrccrsss111", VideoSubSection: 2 } }, { id: 1, name: "Oc", subsection: 1, Video: { id: 13, source: "sourrrcc", VideoSubSection: 1 } }, { id: 1, name: "Oc", subsection: 1, Video: { id: 14, source: "sourrrcc", VideoSubSection: 1 } }],
merged = function (data) {
var r = [], o = {};
data.forEach(function (a) {
if (!(a.id in o)) {
o[a.id] = [];
r.push({ id: a.id, name: a.name, subsection: a.subsection, Video: o[a.id] });
}
o[a.id].push(a.Video);
});
return r;
}(data);
document.write('<pre>' + JSON.stringify(merged, 0, 4) + '</pre>');
Maybe try transform():
_.transform(data, (result, item) => {
let found;
if ((found = _.find(result, { id: item.id }))) {
found.Video.push(item.Video);
} else {
result.push(_.defaults({ Video: [ item.Video ] }, item));
}
}, []);
Using reduce() would work here as well, but transform() is less verbose.
You can do it this way (test is your db output here)
var result = [];
var map = [];
_.forEach(test, (o) => {
var temp = _.clone(o);
delete o.Video;
if (!_.some(map, o)) {
result.push(_.extend(o, {Video: [temp.Video]}));
map.push(o);
} else {
var index = _.findIndex(map, o);
result[index].Video.push(temp.Video);
}
});
console.log(result); // outputs what you want.

Categories

Resources