How can find the sum and count of json data in javascript - javascript

Hi iam trying to group my json data in to sub json data.
here is my json data
[
{
"STATUS":"ACTIVE",
"AMOUNT":200,
"pENDING":100,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":100,
"pENDING":30,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":150,
"pENDING":10,
}
]
and my expected result like
[
{
"STATUS":"ACTIVE",
"COUNT":"1",
"TOTAL AMOUNT":200,
"TOTAL PENDING":100
},
{
"STATUS":"NOTACTIVE",
"COUNT":"2",
"TOTAL AMOUNT":250,
"TOTAL PENDING":40
}
]
I want the separate count ,sum of amount,sum of pending for each status
Could you please help me to find the result

You can do it like this
Idea to handle such things.
so here i am looping through the array and checking for status in the output object. if the status is already in output object i will update the required values. if it's not there than i will create a new one in output object.
let arr =[
{
"STATUS":"ACTIVE",
"AMOUNT":200,
"PENDING":100,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":100,
"PENDING":30,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":150,
"PENDING":10,
}
];
let output = arr.reduce((op,cur)=>{
if(op[cur['STATUS']]){
op[cur['STATUS']]['TOTAL_AMOUNT']+=cur['AMOUNT'];
op[cur['STATUS']]['TOTAL_PENDING']+=cur['PENDING'];
op[cur['STATUS']]['COUNT']++;
} else {
op[cur['STATUS']] ={
'COUNT' : 1,
'TOTAL_AMOUNT' : cur['AMOUNT'],
'TOTAL_PENDING' : cur['PENDING'],
}
}
return op;
},{})
console.log(output);

Trying to fix your own method I would suggest something like this. I tried to do it generic in case you would find it more useful, although this solution would have a problem if the AMOUNT or PENDING entries are not numeric.
const IDENTIFIER = 'STATUS'
const result= {};
data.forEach( entry => {
// Check is this status exists, if not, create one
if(!result[entry[IDENTIFIER]]){
result[entry[IDENTIFIER]] = {}
}
// For each item in the entry add the value
Object.keys(entry).forEach( item => {
// Only sum the items that are not the identifier
if(item !== IDENTIFIER){
result[entry[IDENTIFIER]][item] = (result[entry[IDENTIFIER]][item] || 0) + entry[item];
}
})
});
Hope you find this useful

Try this my friend!
var json = [{
"STATUS":"ACTIVE",
"AMOUNT":200,
"pENDING":100,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":100,
"pENDING":30,
},
{
"STATUS":"NOTACTIVE",
"AMOUNT":150,
"pENDING":10,
}];
var result = [];
var totalActive = 0;
var amountActive = 0;
var pendingActive = 0;
var totalNotActive = 0;
var pendingNotActive= 0;
var amountNotActive = 0;
for(var i=0; i < json.length; i++){
var item = json[i];
if (item.STATUS.toString() == "ACTIVE"){
totalActive +=1;
amountActive = amountActive + item.AMOUNT;
pendingActive = pendingActive + item.pENDING;
}
else
{
totalNotActive +=1;
amountNotActive = amountNotActive + item.AMOUNT;
pendingNotActive = pendingNotActive + item.pENDING;
}
}
result.push({ "STATUS" : "ACTIVE" , "COUNT" : totalActive.toString(), "AMOUNT" : amountActive.toString(), "pENDING" : pendingActive.toString() })
result.push({ "STATUS" : "NOTACTIVE" , "COUNT" : totalNotActive.toString(), "AMOUNT" : amountNotActive.toString(), "pENDING" : pendingNotActive.toString() })
console.log(result);

Related

Filter multiple values with multiple attributes js

I want to filter the multiple attributes with multiple values
'arr' is a list of all products and f_... is the attribute like color or type.
'namet' is the chosen attribute from the user.
'keyt' is the values of each attribute like red, yellow and green.
let arr = [
{ "id": 523, "f_105": ["992","996"], "f_104": ["985"], "f_106":["1000"] },
{ "id": 524, "f_105": ["993","996"], "f_104": ["984"], "f_106":["1001"] }
]
these arrays which user chose for searching
I can get the attrubites like this
var namet = ['f_106', 'f_106', 'f_105', 'f_105', 'f_104' ];
var keyt = ['1000' , '1001', '993', '996', '985'];
OR
var chooenKey = ['f_106', 'f_105', 'f_104']
var chosenAttr = {
"f_106": ["1000", "1001"],
"f_105": ["993", "996"],
"f_104": ["985"],
}
OR
var chosenAttr =
[
{"f_106": ["1000", "1001"]},
{"f_105": ["993", "996"]},
{"f_104": ["985"]}
]
I want a method to loop to get result like variable 'filtered'
var filtered = d =>
(d.f_106.indexOf("1000") > -1 || d.f_106.indexOf("1001") > -1) &&
(d.f_105.indexOf("993") > -1 || d.f_105.indexOf("996") > -1) &&
(d.f_104.indexOf("985") > -1)
then put it here
const f = arr.filter(filtered);
You can also give another type to filter the product with multiple attributes.
If you examine the example I sent, I believe it will solve your problem.
let arr = [
{ "id": 523, "f_105": ["992", "996"], "f_104": ["985"], "f_106": ["1000"] },
{ "id": 524, "f_105": ["993", "996"], "f_104": ["984"], "f_106": ["1001"] }
]
var chosenAttr =
[
{ "f_106": ["1000", "1001"] },
{ "f_105": ["992"] },
{ "f_104": ["985"] }
]
function filterArr() {
var arrCopy = arr;
for (i = 0; i < chosenAttr.length; i++) {
for (var key in chosenAttr[i]) {
arrCopy = arrCopy.filter(function (item) {
var is_match = false;
for (var idx in chosenAttr[i][key]) {
let val = chosenAttr[i][key][idx];
if (item[key].indexOf(val) > -1) {
is_match = true;
}
}
return is_match;
});
}
}
return arrCopy;
}
var filterData = filterArr();
$('#response').html(JSON.stringify(filterData));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<pre>
<code id="response">
</code>
</pre>

Get values from JSON file and sort by key number value

I was wondering if someone could help me get this to work so it prints out values and sorts them by propertyCount, highest to lowest. Below gets me the the first 6 values from a JSON file.
Basically, Im trying to only grab 6 values from a JSON file where it's sorted by a key called count that has a number value. Any help is greatly appreciated.
var countyInfo = [];
var count = 0;
var propertyCount = 0;
function getCountyInfo($j) {
//$j.ajax({
// url: "/info.json?st=WA"
//}).done(function(data) {
//countyInfo = data;
countyInfo = getDataDemo();
$j.each(countyInfo.counts.county_info, function(key, value) {
$j.each(value, function(key, value) {
if (key == "count") {
propertyCount = value;
}
if (key == "countyName" && value != null) {
var countyName = value;
if (count < 6) {
$j('#countyList').append('<li class="topCountyRow">' + countyName + ' (' + propertyCount + ')</li>');
}
count++;
}
});
});
//});
}
(function($j) {
//loaded();
var county_info = [];
getCountyInfo($j);
})(jQuery);
// Just for the StackOverflow Question
function getDataDemo() {
return JSON.parse(`{
"state": "wa",
"stateName": "Washington",
"counts": {
"county_info": [
{
"count": 72,
"countyName": "Anderson"
},
{
"count": 43,
"countyName": "Angelina"
}
]
}
}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="countyList" class="ulTwoColumns"></ul>
You can use sort function of array where you need to pass comparer function as below.
function sort(data)
{
return data.counts.county_info.sort((left,right)=>{
return left.count<right.count?1:-1;
})
}
Updated as per your data.
Use the sort method to compare and sort
data.counts.county_info.sort(a, b => a.count < b.count);
Implementing in your code above
function getCountyInfo(){
$j.ajax({
url: "/info.json?st=WA"
}).done(function(data) {
let sortedData = data.counts.county_info.sort(a, b => a.count < b.count);
// other things to do
});
}

Underscore Equivalent to Javascript For Loop?

I'd like to convert this code:
for (var i = 0; i < product.ages.length; i ++){
for (var j = 0; j < $scope.ages.length; j ++){
if (product.ages[i].id == $scope.ages[j].id){
$scope.ages[j]['ticked'] = true;
}
}
}
into underscore.js. please help.
Another way to solve this problem would be to first create a hash of the scope.ages using underscore's indexBy:
var scope_ages = _.indexBy($scope.ages, 'id');
The object would look something like:
{
1: ref to scope.ages with id 1,
2: ref to scope.ages with id 2,
etc.
}
Then iterate over the product ages using each to set the ticked value:
_.each(product.ages, age => scope_ages[age.id].ticked = true)
var product = {
ages: [
{ id : 1 }
]
}
var $scope = {
ages: [
{ id : 0, ticked: false },
{ id : 1, ticked: false },
{ id : 2, ticked: false },
]
}
var scope_ages = _.indexBy($scope.ages, 'id');
_.each(product.ages, age => scope_ages[age.id].ticked = true)
document.getElementById('scope_ages').textContent = JSON.stringify(scope_ages);
document.getElementById('result').textContent = JSON.stringify($scope.ages);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.2/underscore.js"></script>
<h1>scope_ages</h1>
<p>
<pre id="scope_ages"></pre>
</p>
<h1>Scope</h1>
<p>
<pre id="result"></pre>
</p>
This would be your code in underscore:
_.each(product.ages, function(pAge) {
_.each($scope.ages, function(sAge) {
if (pAge.id === sAge.id) {
sAge.ticked = true;
}
});
});
Here is an example on how you do an _.each on an object.
var example = {"hello":"world", "this":"is", "super":"neat"};
_.each(example, function(value, index){
console.log(index + ":" + value);
}
->hello:world
->this:is
->super:neat
You can use _.find
_.each($scope.ages, function(v){
v.ticked = _.find(product.ages, function(a){
return v.age === a.age;
})?true:false;
})
Also, just a pointer, you should use break on match.

Get the level of a hierarchy

I have an array of objects, Where each object has an id and a ParentId property (so they can be arranged in trees). They are in no particular order.
Please note that the id's and parentId's will not be integers, they will be strings (just wanted to have the sample code cleaner..)
There is only one root: lets say its id:1
The data looks like so:
data = [
{
id:"id-2",
parentId:"id-3"
},
{
id:"id-4",
parentId:"2"
},
{
id:"id-3",
parentId:"id-4"
},
{
id:"id-5",
parentId:"id-4"
},
{
id:"id-6",
parentId:"id-1"
},
{
id:"id-7",
parentId:"id-1"
}
// and so on...
]
I am looking for a efficient way to give each object a level property which should specify the nested level it is...
They should then look like this:
data = [
{
id:"id-2",
parentId:"id-1",
level:2
},
{
id:"id-3",
parentId:"id-4",
level:5
},
{
id:"id-4",
parentId:"id-2",
level:3
},
{
id:"id-5",
parentId:"id-4",
level:5
},
{
id:"id-6",
parentId:"id-1",
level:2
},
{
id:"id-7",
parentId:"id-3",
level:4
}
// and so on...
]
In short:
I want that level to be added dynamically via looping thru the array and figuring out the hierarchy..
Additionally, (if posible) they should then be sorted according to there order, like for instance all objects level:3's from the same parent should be next to each other, not that there should be siblings of the same parent next to each other rather then two cousins of level 3 next to each other.
A working example of the below code is on jsFiddle.
Index the tree by id and traverse it upwards, from each node, and count until you hit the root. By indexing first, we approach O(n) time complexity (depending on tree density). ****Updated to satisfy the sorting requirement, and allow exclusion of root node***:
function levelAndSort(data, startingLevel) {
// indexes
var indexed = {}; // the original values
var nodeIndex = {}; // tree nodes
var i;
for (i = 0; i < data.length; i++) {
var id = data[i].id;
var node = {
id: id,
level: startingLevel,
children: [],
sorted: false
};
indexed[id] = data[i];
nodeIndex[id] = node;
}
// populate tree
for (i = 0; i < data.length; i++) {
var node = nodeIndex[data[i].id];
var pNode = node;
var j;
var nextId = indexed[pNode.id].parentId;
for (j = 0; nextId in nodeIndex; j++) {
pNode = nodeIndex[nextId];
if (j == 0) {
pNode.children.push(node.id);
}
node.level++;
nextId = indexed[pNode.id].parentId;
}
}
// extract nodes and sort-by-level
var nodes = [];
for (var key in nodeIndex) {
nodes.push(nodeIndex[key]);
}
nodes.sort(function(a, b) {
return a.level - b.level;
});
// refine the sort: group-by-siblings
var retval = [];
for (i = 0; i < nodes.length; i++) {
var node = nodes[i];
var parentId = indexed[node.id].parentId;
if (parentId in indexed) {
var pNode = nodeIndex[parentId];
var j;
for (j = 0; j < pNode.children.length; j++) {
var child = nodeIndex[pNode.children[j]];
if (!child.sorted) {
indexed[child.id].level = child.level;
retval.push(indexed[child.id]);
child.sorted = true;
}
}
}
else if (!node.sorted) {
indexed[node.id].level = node.level;
retval.push(indexed[node.id]);
node.sorted = true;
}
}
return retval;
}
Example:
// level 0 (root) excluded
var startingLevel = 1;
var someData = [
{id : "id-1", parentId : "id-0"},
{id : "id-2", parentId : "id-0"},
{id : "id-3", parentId : "id-2"},
{id : "id-4", parentId : "id-3"},
{id : "id-5", parentId : "id-4"},
{id : "id-6", parentId : "id-4"},
{id : "id-7", parentId : "id-0"},
{id : "id-8", parentId : "id-1"},
{id : "id-9", parentId : "id-7"},
{id : "id-10", parentId : "id-1"},
{id : "id-11", parentId : "id-1"},
{id : "id-12", parentId : "id-1"}
];
var outputArray = levelAndSort(someData, startingLevel);
Output:
Note
If you change the input order, the sort comes out a little different, but it's still correct (i.e., in level-order, grouped by sibling).
I'm not sure where you get the value for level so I'll assume that its just an integer. BTW, you can add the level property to each of your array's item by looping through it.
for (var i = 0, l = data.length; i < l; i++) {
data[i].level = i
}
which will give
data = [{id:"1", parentId:"3", level:0 }, {id:"2", parentId:"1", level:1 } ...]
Here is your working code. Level starts at 2.
ALERT: If a level cannot be calculated, the application may go into an infinite loop. So, make sure the parentId is valid for all objects and at least one of them have parentId="id-1".
<script type="text/javascript">
data = [
{
id:"id-2",
parentId:"id-3"
},
{
id:"id-4",
parentId:"id-2"
},
{
id:"id-3",
parentId:"id-5"
},
{
id:"id-5",
parentId:"id-1"
}
];
function processData() {
flag = true;
while(flag) {
flag = false;
for(var i = 0; i < data.length; i++) {
if(data[i].parentId == "id-1") {
data[i].level = 2;
} else {
l = getLevel(data[i].parentId);
if(l > 0) {
data[i].level = l + 1;
} else {
flag = true;
}
}
}
}
}
function getLevel(id) {
for(var i = 0; i < data.length; i++) {
if(data[i].id == id) {
if(data[i].level) {
return data[i].level;
} else {
return 0;
}
}
}
return 0;
}
processData();
console.log(data);
</script>
One way to address this without the need for recursion is to create a DOM hierarchy. For each item in the array, create a div and attach it to its parent. then walk the DOM and assign the levels (top is level 1, then add 1 for each child).
I have set up a rough demo here:
http://jsfiddle.net/4AqgM/
An excerpt from the code:
top.dataset.level="1";
var topChildren=top.getElementsByTagName("div");
for (var i=0;i<topChildren.length;i++) {
topChildren[i].dataset.level=parseInt(topChildren[i].parentNode.dataset.level)+1;
}

Get name of key in key/value pair in JSON using jQuery?

Say I have this JSON:
[
{
"ID": "1",
"title": "Title 1",
},
{
"ID": "2",
"title": "Title 2",
}
]
How would I return the set of key names that recur for each record? In this case, ID, title.
I tried:
$.getJSON('testing.json', function(data) {
var items = [];
$.each(data, function(key, val) {
items.push(key +', ');
});
$('<p/>', {
html: items.join('')
}).appendTo('#content');
});
without success.
This is a JSON "database", and every "record" has the same keys. I just want a script that will tell me what the keys are, not test whether or not they occur in every entry.
This will give you an array of all the string properties that match across an array of objects. Is that what you are looking for?
$.getJSON('testing.json', function(data) {
var propertiesThatExistInAll = getPropertiesThatExistInAll(data);
});
var getPropertiesThatExistInAll = function(arr) {
var properties = $.map(data[0], function (prop, value) {
return prop;
});
var propertiesThatExistInAll = [];
$.each(properties, function (index, property) {
var keyExistsInAll = true;
// skip the first one since we know it has all the properties
for (var i = 1, len = data.length; i < len; i++) {
if (!data[i].hasOwnProperty(property)) {
keyExistsInAll = false;
break;
}
}
if (keyExistsInAll) {
propertiesThatExistInAll.push(property);
}
});
return propertiesThatExistInAll;
};
Something like this, perhaps?
items = [];
for (key in jsonobj) {
if (!itemExists(items, key)) {
items[items.length] = key
}
}
function itemExists(items, value) {
for (i = 0; i < items.length; i++) {
if (items[i] == value) {
return true
}
}
return false;
}
Of course, that will return items that exist in any one of the objects, not that exist in all. It's not entirely clear from your question if this is the solution you want.
This can probably be made more efficient/concise, but the function below will do it.
var testJson = [ {'oi' : 1, 'arf': 2, 'foo' : 0}, {'oi': 5, 'arf': 7}];
function commonKeys(j)
{
var fillUp = [];
for(var i in j[0])
fillUp.push(i);
for(var i = 1; i < j.length; i++)
{
var cur = j[i]; var curArr = [];
for (var i in cur) {curArr.push(i)};
fillUp = fillUp.filter(function(x) {return (curArr.indexOf(x) != -1);});
}
return fillUp;
}
alert(commonKeys(testJson)); //oi,arf (not foo)

Categories

Resources