Javascript get data totals into list - javascript

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; }

Related

Rename keys in reduce function

I am essentially receiving data from another API that takes the following structure
const ob = {
"dataOne": [
{
"type": "Type 1",
"name": "email.failed"
},
{
"type": "Type 1",
"name": "email.success"
},
{
"type": "Type 2",
"name": "email.success"
},
{
"type": "Type 3",
"name": "email.success"
},
],
};
What I was doing what creating a new array which essentially gets each unique type and then does a total count and an individual count of each unique name.
I also have another data set I combine with this but omitted for this question.
The working code I have is
const ob = {
"dataOne": [
{
"type": "Type 1",
"name": "email.failed"
},
{
"type": "Type 1",
"name": "email.success"
},
{
"type": "Type 2",
"name": "email.success"
},
{
"type": "Type 3",
"name": "email.success"
},
],
};
const dataReduced = ob.dataOne.reduce((acc, o) => {
if (!acc[o.type]) {
acc[o.type] = [
{
count: 0,
'email.success': 0,
'email.failed': 0,
},
];
}
acc[o.type][0].count = (acc[o.type][0].count || 0) + 1;
acc[o.type][0][o.name] = acc[o.type][0][o.name] + 1;
return acc;
}, {});
console.log(dataReduced);
What I can't figure out however, because it is matching on email.success is how to rename these in my final output. I essentially want to remove the email. part.
So instead, the console.log should be
{
Type 1: [{
count: 2,
failed: 1,
success: 1
}],
Type 2: [{
count: 1,
failed: 0,
success: 1
}],
Type 3: [{
count: 1,
failed: 0,
success: 1
}]
}
How would I achieve this?
Thanks
You can do something like this
const ob = {
"dataOne": [
{
"type": "Type 1",
"name": "email.failed"
},
{
"type": "Type 1",
"name": "email.success"
},
{
"type": "Type 2",
"name": "email.success"
},
{
"type": "Type 3",
"name": "email.success"
},
],
};
const dataReduced = ob.dataOne.reduce((acc, o) => {
const name = o.name.replace('email.', '')
if (!acc[o.type]) {
acc[o.type] = [
{
count: 0,
'success': 0,
'failed': 0,
},
];
}
acc[o.type][0].count = (acc[o.type][0].count || 0) + 1;
acc[o.type][0][name] = acc[o.type][0][name] + 1;
return acc;
}, {});
console.log(dataReduced);
I've no clue why the console output is actually in your Browser console and not in this JS Constainer, but here, no reduce, but I don't even see the reason why a reduce would be better here:
var arr = [
{
"type": "Type 1",
"name": "email.failed"
},
{
"type": "Type 1",
"name": "email.success"
},
{
"type": "Type 2",
"name": "email.success"
},
{
"type": "Type 3",
"name": "email.success"
},
];
var result = [];
for (var o of arr) {
if (!result.hasOwnProperty(o.type)) {
var newObj = {
count: 1,
failed: 0,
success: 0,
};
if (o.name.indexOf('failed') !== -1) {
newObj.failed++;
}
if (o.name.indexOf('success') !== -1) {
newObj.success++;
}
result[o.type] = [newObj];
} else {
result[o.type][0].count++;
if (o.name.indexOf('failed') !== -1) {
result[o.type][0].failed++;
}
if (o.name.indexOf('success') !== -1) {
result[o.type][0].success++;
}
}
}
console.log(result);
I resolved this using the for in loop:
for(let elem in dataReduced){
dataReduced[elem][0]['success'] = dataReduced[elem][0]['email.success'];
dataReduced[elem][0]['failed'] = dataReduced[elem][0]['email.failed'];
delete dataReduced[elem][0]['email.success'];
delete dataReduced[elem][0]['email.failed'];
}

combine values to an array with same id For JSON object

after join operation, I get JSON object with duplicate id values
how it is possible to map them with their association property to an array with javascript
{
"id": 1,
"name": "doc 1",
"appointmentTime": "2018-12-28T00:00:43"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-25T23:00:53"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-26T23:00:02"
},
{
"id": 3,
"name": "doc3",
"appointmentTime": null
},
I want something like that
{
"id": 1,
"name": "doc1",
"appointmentTime": ["2018-12-28T00:00:43"]
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": ["2018-12-26T23:00:02","2018-12-26T23:00:02"]
},
{
"id": 3,
"name": "doc3",
"appointmentTime": null
},
You will need reduce function for that:
const src = [{
"id": 1,
"name": "doc 1",
"appointmentTime": "2018-12-28T00:00:43"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-25T23:00:53"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-26T23:00:02"
},
{
"id": 3,
"name": "doc3",
"appointmentTime": null
}]
const result = src.reduce((acc, {id, name, appointmentTime}) => {
const existing = acc.find(i => i.id === id)
if (existing) { existing.appointmentTime.push(appointmentTime) }
else {acc.push({id, name, appointmentTime: [appointmentTime]})}
return acc
}, [])
console.log(result)
I also used destructuring assignment
> let mergeDuplicates = (arr, uniqueKey, mergeKey) => {
> let hashMap = {}; arr.forEach(item => {
>
> if(hashMap[item[uniqueKey]] == null) { item[mergeKey] = [item[mergeKey]]; hashMap[item[uniqueKey]] = item; }
> else { hashMap[item[uniqueKey]][mergeKey].push(item[mergeKey]); }
> let ansArr = [];
> for(var key in hashMap){
> ansArr.push(hashMap[key]);
> }
> return ansArr;
>
> })
>
> }
> myarray = mergeDuplicates(myarray, "id", "appointmentTime");
i would do it like this:
//lets say you got your jsonObj already in an Array like:
var myarray = [{
"id": 1,
"name": "doc 1",
"appointmentTime": "2018-12-28T00:00:43"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-25T23:00:53"
},
{
"id": 2,
"name": "doc 2",
"appointmentTime": "2018-12-26T23:00:02"
},
{
"id": 3,
"name": "doc3",
"appointmentTime": null
}
];
//just loop through your data and combine it
for (var i = 0; i < myarray.length; i++) {
//And loop again for duplicate data
for (var j = i + 1; j < myarray.length; j++) {
if (myarray[i].id == myarray[j].id) {
var tmp = myarray[j].appointmentTime;
myarray[j].appointmentTime = [];
myarray[j].appointmentTime.push(tmp);
myarray[j].appointmentTime.push(myarray[i].appointmentTime);
myarray[i] = {};
}
}
}
console.log(myarray);
remove afterwards all empty jsonobj
https://jsfiddle.net/m073qwr6/1/

Jquery how to query Json Object with multiple where clause

How do I query multiple columns/properties from a json object?
I am trying this to query single column "category". How can Query with both Category and Id?
var data = {
"items": [{
"id": 1,
"category": ["cat1","cat2"]
}, {
"id": 2,
"category": ["cat1","cat3"]
}, {
"id": 3,
"category": ["cat11","cat2"]
}]
};
var returnedData = $.grep(data.items, function (element) {
return element.category.indexOf('cat1') >= 0;
});
console.log(returnedData);
Instead of using the slower grep, use plain js filter
var data = {
"items": [{
"id": 1,
"category": ["cat1","cat2"]
}, {
"id": 2,
"category": ["cat1","cat3"]
}, {
"id": 3,
"category": ["cat11","cat2"]
}]
};
const res = data.items.filter(e => e.category.indexOf('cat1') >= 0 && e.id === 1);
console.log(res);
Not sure exactly what you are asking but -
return element.category.indexOf('cat1') >= 0 && element.id == 2;
**return element.category.includes('cat1') && element.id!=1;**
This way you can achieve this
var data = {
"items": [{
"id": 1,
"category": ["cat1","cat2"]
}, {
"id": 2,
"category": ["cat1","cat3"]
}, {
"id": 3,
"category": ["cat11","cat2"]
}]
};
var returnedData = $.grep(data.items, function (element) {
return element.category.includes('cat1') && element.id!=1;
});
console.log(returnedData);
Live Demo

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)

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

Categories

Resources