Javascript object sum values of same property key - javascript

I Have the following object and I want to sum the values of the same ingredients name, like: tomato: 5, chicken:5, rice: 1, peas: 1, i have this code but is not making the sum, instead is showing all the objects
var data3 = {
"menus": [{
"recipe": "chicken with rice",
"ingredients": [{
"name": "tomato",
"value": 2
}, {
"name": "chicken",
"value": 3
}, {
"name": "rice",
"value": 1
}]
}, {
"recipe": "Garden rice",
"ingredients": [{
"name": "tomato",
"value": 3
}, {
"name": "chicken",
"value": 2
}, {
"name": "peas",
"value": 1
}]
}]
};
var ingredients;
for (var i = 0; i < 10; i++) {
ingredients = data3.menus[i].ingredients;
var temp = {};
var obj = null;
for (var j = 0; j < ingredients.length; j++) {
obj = ingredients[j];
if (!temp[obj.name]) {
temp[obj.name] = obj;
} else {
temp[obj.name].value += obj.value;
}
}
var result = [];
for (var prop in temp)
result.push(temp[prop]);
console.log(result);
};
I will appreciate your help, thanks!

You could use a hash table with the name of the ingredient and use a default value of zero if a property does not exist. Then add the value.
var data3 = { menus: [{ recipe: "chicken with rice", ingredients: [{ name: "tomato", value: 2 }, { name: "chicken", value: 3 }, { name: "rice", value: 1 }] }, { recipe: "Garden rice", ingredients: [{ name: "tomato", value: 3 }, { name: "chicken", value: 2 }, { name: "peas", value: 1 }] }] },
ingredients = Object.create(null);
data3.menus.forEach(function (a) {
a.ingredients.forEach(function (b) {
ingredients[b.name] = (ingredients[b.name] || 0) + b.value;
});
});
console.log(ingredients);

Your implementation is correct, just you were re-initializing temp again and again. So you just need to take temp out of your for loop.
var data3 = {
"menus": [{
"recipe": "chicken with rice",
"ingredients": [{
"name": "tomato",
"value": 2
}, {
"name": "chicken",
"value": 3
}, {
"name": "rice",
"value": 1
}]
}, {
"recipe": "Garden rice",
"ingredients": [{
"name": "tomato",
"value": 3
}, {
"name": "chicken",
"value": 2
}, {
"name": "peas",
"value": 1
}]
}]
};
var ingredients;
var temp = {};
for (var i = 0; i < data3.menus.length; i++) {
ingredients = data3.menus[i].ingredients;
var obj = null;
for (var j = 0; j < ingredients.length; j++) {
obj = ingredients[j];
if (!temp[obj.name]) {
temp[obj.name] = obj;
} else {
temp[obj.name].value += obj.value;
}
}
};
var result = [];
for (var prop in temp)
result.push(temp[prop]);
console.log(result);

You can create a function that will traverse all ingredients and if ingredient.name has given name, then add ingredient.value to your result. Here is ES2015 solution with arrow functions:
const sumIngredients = (menus, name) => {
let result = 0;
menus.forEach(meal => {
meal.ingredients.forEach(ingredient => {
if (ingredient.name === name) {
result += ingredient.value;
}
})
})
return result;
}
The use it:
sumIngredients(data3.menus, 'chicken'); //5
sumIngredients(data3.menus, 'tomato'); //5
sumIngredients(data3.menus, 'rice'); //1
sumIngredients(data3.menus, 'peas'); //1
Working example: https://jsfiddle.net/sc8wrupk/

Related

JSON data formatting through dynamic Key, Value

I have a JSON response data. I want to display it as a tabular format but I am not able to do it correctly. please correct me where I am doing wrong.
Response Data
const response = [
{
"key": "Name",
"data": [ "Tom", "Mark", "Jack" ]
},
{
"key": "OfcLocation",
"data": [ "USA", "Spain", "Japan" ]
},
{
"key": "IPAddress",
"data": [ "XX.XXX.X.XX", "XX.XXX.X.XX", "XX.XXX.X.XX" ]
},
{
"key": "Port",
"data": [ "4300", "4080", "9200" ]
},
{
"key": "Role",
"data": [ "Admin", "Limited", "Admin" ]
}
];
Desired Output Format
[
{ "Name": "Tom", "OfcLocation": "USA", "IPAddress": "XX.XXX.X.XX", "Port": "4300", "Role": "Admin" },
{ "Name": "Mark", "OfcLocation": "Spain", "IPAddress": "XX.XXX.X.XX", "Port": "4080", "Role": "Limited" },
{ "Name": "Jack", "OfcLocation": "Japan", "IPAddress": "XX.XXX.X.XX", "Port": "9200", "Role": "Admin" }
]
Code
let formatedData = [];
let rowArr = {};
for( let i=0; i< response.length; i++) {
for( let j=0;j< response[i].data.length; j++) {
rowArr[response[i].key] = response[i].data[j];
}
formatedData.push(rowArr);
}
You can get the result you want using Array.reduce function.
const response = [
{
"key": "Name",
"data": [ "Tom", "Mark", "Jack" ]
},
{
"key": "OfcLocation",
"data": [ "USA", "Spain", "Japan" ]
},
{
"key": "IPAddress",
"data": [ "XX.XXX.X.XX", "XX.XXX.X.XX", "XX.XXX.X.XX" ]
},
{
"key": "Port",
"data": [ "4300", "4080", "9200" ]
},
{
"key": "Role",
"data": [ "Admin", "Limited", "Admin" ]
}
];
const result = response.reduce((acc, cur) => {
cur.data.forEach((item, index) => {
if (acc.length <= index) {
acc.push({
[cur.key]: item
});
} else {
acc[index][cur.key] = item;
}
});
return acc;
}, []);
console.log(result);
You need to switch the inner and outer loop and put let rowArr = {}; inside the outer loop
let formatedData = [];
let rowArr = {};
for (let j = 0; j < response[0].data.length; j++) {
let rowArr = {};
for (let i = 0; i < response.length; i++) {
rowArr[response[i].key] = response[i].data[j];
}
formatedData.push(rowArr);
}
Make an array of empty objects and put the data in them...
let sortedArray = [];
for(let i=0 ; i< response[0].data.length ; i++){
sortedArray.push(new Object);
}
function sort() {
response.forEach((el) => {
el.data.forEach((elem, i) => {
sortedArray[i][el.key] = elem;
});
});
}
sort();
console.log(sortedArray);

Sorting JSON alphabetically by first letter

I have a JSON like this:
[
{
"id": 1,
"slug": "abakan",
"name": "Абакан"
},
{
"id": 4,
"slug": "almetevsk",
"name": "Альметьевск"
},
{
"id": 10,
"slug": "astrahan",
"name": "Астрахань"
},
{
"id": 11,
"slug": "barnaul",
"name": "Барнаул"
},
...
]
And getting this by this method:
public function getCities()
{
$cities = City::mainCities()->get(['id', 'slug', 'name']);
return response()->json($cities);
}
How can i sort this list alphabetically and with their letters. For example:
"A": [
{
"id": 1,
"slug": "abakan",
"name": "Абакан"
},
{
"id": 4,
"slug": "almetevsk",
"name": "Альметьевск"
}
],
"B": [
{
"id": 11,
"slug": "barnaul",
"name": "Барнаул"
},
...
]
and so on...
I have Laravel on the backend and VueJS on front.
My solution:
var cities = [
{ id: 1, slug: "abakan", name: "Абакан" },
{ id: 4, slug: "almetevsk", name: "Альметьевск" },
{ id: 11, slug: "barnaul", name: "Барнаул" },
{ id: 10, slug: "astrahan", name: "Астрахань" }
];
cities.sort(function(a, b) {
return a.slug[0].localeCompare(b.slug[0]);
});
var newCities = {};
for (var i = 0; i < cities.length; i++) {
var c = cities[i].slug[0].toUpperCase();
if (newCities[c] && newCities[c].length >= 0)
newCities[c].push(cities[i]);
else {
newCities[c] = [];
newCities[c].push(cities[i]);
}
}
console.log(newCities);
This works for me:
var items = [
{
"id": 11,
"slug": "barnaul",
"name": "Барнаул"
},
{
"id": 1,
"slug": "abakan",
"name": "Абакан"
},
{
"id": 4,
"slug": "almetevsk",
"name": "Альметьевск"
},
{
"id": 10,
"slug": "astrahan",
"name": "Астрахань"
}
];
var sortedItems = items.sort((a, b) => a.slug.localeCompare(b.slug));
var results = {};
for (var i = 0; i < 26; i++) {
var char = String.fromCharCode(97 + i);
var bigChar = char.toUpperCase();
results[bigChar] = [];
for (var s = 0; s < sortedItems.length; s++) {
if (sortedItems[s].slug.startsWith(char)) {
results[bigChar].push(sortedItems[s]);
}
}
}
console.log(results)

Javascript get data totals into list

I have this data:
{
"id": "123",
"name": "name here",
"thsub": {
"637": {
"id": "637",
"name": "Sub 1",
"stats": {
"items": 5,
},
"ons": null
},
"638": {
"id": "638",
"name": "Sub 2",
"stats": {
"items": 10,
},
"ons": null
}
},
"ph": 10,
}
Here's is the code:
mydata = [mydata];
var chList=[];
var thList=[];
var thCount=[];
for (var i = 0; i < mydata.length; i++) {
var obj = mydata[i];
var cl = obj.name;
if (obj.thsub != null) {
chList.push(cl);
}
if(obj.thsub) {
if (i < 10) {
var nme = Object.keys(obj.thsub).map( function(key){
var item = obj.thsub[key];
return item.name;
});
thCount.push(numberofitems);
thList = thList.concat(nme);
thCount = thCount.concat(Array(nme.length).fill(nme.length));
}
}
}
My problem is in the thCount ... what I need to do is to count each "items" on obj.thsub.638 or other ...stats.items and put the totals into thCount like I've got in thList.
So the desired result woule be 5 and 10 in other words: [5, 10] in this case.
thCount would be [5, 10]
How can I do this?
you should access the json objects using key value, index is for arrays. below code just does the thcount for you
var data = {
"id": "123",
"name": "name here",
"thsub": {
"637": {
"id": "637",
"name": "Sub 1",
"stats": {
"items": 5,
},
"ons": null
},
"638": {
"id": "638",
"name": "Sub 2",
"stats": {
"items": 10,
},
"ons": null
}
},
"ph": 10,
};
var thCount = [];
for(key in data.thsub ){
if(data.thsub[key].stats){
thCount.push(data.thsub[key].stats.items);
}
}
console.log(thCount);
Object.values gives you the list of values of a given object and then you can map your result in an array. in ES5:
var arr = Object.values(mydata.thsub).map(function(item) {
return item.stats.items
});
in ES6:
const list = Object.values(mydata.thsub).map(item => item.stats.items);
You could use an iterative recursive approach for getting the wanted values.
function getValues(object, key) {
function iter(o) {
if (key in o) {
result.push(o[key]);
}
Object.keys(o).forEach(function (k) {
if (o[k] && typeof o[k] === 'object') {
iter(o[k]);
}
});
}
var result = [];
iter(object);
return result;
}
var data = { id: "123", name: "name here", thsub: { 637: { id: "637", name: "Sub 1", stats: { items: 5, }, ons: null }, 638: { id: "638", name: "Sub 2", stats: { items: 10, }, ons: null } }, ph: 10, };
console.log(getValues(data, 'items'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Underscore Convert array to object keys

I am trying to convert this array to an object. Using underscore, I want to convert this array :
[
{
"id": "parentA",
"children": [
{
"name": "name1"
},
{
"name": "name2"
},
{
"name": "name3"
}
]
},
{
"id": "parentB",
"children": [
{
"name": "name4"
},
{
"name": "name5"
},
{
"name": "name6"
}
]
}]
into an object that looks like this:
{
"name1": "parentA",
"name2": "parentA",
"name3": "parentA",
"name4": "parentB",
"name5": "parentB",
"name6": "parentB"
}
I'm really just looking for the cleanest/simplest way possible.
Here's a fairly short way to do it with two reduce:
var data = [
{
"id": "parentA",
"children": [
{
"name": "name1"
},
{
"name": "name2"
},
{
"name": "name3"
}
]
},
{
"id": "parentB",
"children": [
{
"name": "name4"
},
{
"name": "name5"
},
{
"name": "name6"
}
]
}];
var out = _.reduce(data, function(result, parent) {
_.reduce(parent.children, function(r, child) {
r[child.name] = parent.id;
return r;
}, result);
return result;
}, {});
document.write(JSON.stringify(out));
<script src="http://underscorejs.org/underscore-min.js"></script>
var a = [{
"id": "parentA",
"children": [{
"name": "name1"
}, {
"name": "name2"
}, {
"name": "name3"
}]
}, {
"id": "parentB",
"children": [{
"name": "name4"
}, {
"name": "name5"
}, {
"name": "name6"
}]
}];
var new_obj = {};
var len = a.length;
for (j = 0; j < len; j++) {
var c = $.extend({}, a[j]);
var children_length = (c.children).length;
for (i = 0; i < children_length; i++) {
var temp = ((a[j].children)[i]).name;
new_obj[temp] = c.id;
}
}
document.write(JSON.stringify(new_obj));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
You'll only need to use underscore if you're supporting browsers without native reduce and forEach array methods, but you can do it like this.
var result = _.reduce(array, function(memo, entry) {
_.each(entry.children, function(child) {
memo[child.name] = entry.id;
});
return memo;
}, {});
function expand(list){
return _.reduce(list,function(a,b) {
_.each(b.children, function(c) {
a[c.name] = b.id;
});
return a;
},{});
}
Check the output for your sample here

jqTree - creating tree data from json

I'm trying to display a tree using jqTree - http://mbraak.github.com/jqTree
I need help with creating the tree data from JSON.
My JSON data looks like this:
{
"d" : {
"results": [
{
"Title": "Committee A",
"ReportsToId": null,
"Rank": 1,
"Id": 5
},
{
"Title": "Committee B",
"ReportsToId": 5,
"Rank": 2,
"Id": 7
},
{
"Title": "Committee C",
"ReportsToId": 7,
"Rank": 3,
"Id": 13
},
{
"Title": "Committee D",
"ReportsToId": 13,
"Rank": 4,
"Id": 1
},
{
"Title": "Committee E",
"ReportsToId": 13,
"Rank": 4,
"Id": 3
}
]
}
}
I want to end up with this:
var treeData = [
{
label: 'Committee A',
children: [
{
label: 'Committee B',
children: [
{
label: 'Committee C',
children: [
{ label: 'Committee D' },
{ label: 'Committee E' }
]
}]
}
]
}
];
Here's a solution adapted from http://www.jqwidgets.com/populating-jquery-tree-with-json-data/:
var jqTreeData = function (data) {
var source = [];
var items = [];
// build hierarchical source.
for (i = 0; i < data.length; i++) {
var item = data[i];
var title = item["Title"];
var reportsToId = item["ReportsToId"];
var id = item["Id"];
if (items[reportsToId]) {
var item =
{
label: title
};
if (!items[reportsToId].children) {
items[reportsToId].children = [];
}
items[reportsToId].children[items[reportsToId].children.length] = item;
items[id] = item;
}
else {
items[id] =
{
label: title
};
source[0] = items[id];
}
}
return source;
}

Categories

Resources