I was wondering if there was a better or smarter way of sorting objects in JavaScript when sorting for multiple items?
For example, if I have the following JSON:
json = [
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "truck", "year": 2021, "origin": "USA" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "truck", "year": 2020, "origin": "CA" },
{ "type": "bike", "year": 2000, "origin": "AUS" }
]
If I wanted to sort it by type then year how would I do that in the same .sort function?
I've currently got it doing one, then the other - but when I try to combine them it doesn't seem to output correctly:
// one after other
json.sort( ( a, b ) => {
a = a.type.toLowerCase();
b = b.type.toLowerCase();
return a < b ? -1 : a > b ? 1 : 0;
})
.sort( ( a, b ) => {
a = a.year;
b = b.year;
return a < b ? -1 : a > b ? 1 : 0;
});
Returning:
[
{ "type": "bike", "year": 2000, "origin": "AUS" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "truck", "year": 2020, "origin": "USA" },
{ "type": "truck", "year": 2021, "origin": "CA" }
]
When it should return (all the types together, then by year):
[
{ "type": "bike", "year": 2000, "origin": "AUS" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "truck", "year": 2020, "origin": "USA" },
{ "type": "truck", "year": 2021, "origin": "CA" }
]
In the sort callback, compare the items' type property. If one is lexographically greater/smaller, sort it before/after the other item accordingly.
Otherwise, you can return the result after subtracting the two items' year property:
const arr = [
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "truck", "year": 2021, "origin": "USA" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "truck", "year": 2020, "origin": "CA" },
{ "type": "bike", "year": 2000, "origin": "AUS" }
]
const sorted = arr.sort((a,b) => a.type.localeCompare(b.type) || a.year - b.year)
console.log(sorted)
Credit to DraganS
If you don't want the comparison to be case-sensitive, you can set localeCompare's sensitivity option to accent:
const arr = [
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "truck", "year": 2021, "origin": "USA" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "truck", "year": 2020, "origin": "CA" },
{ "type": "bike", "year": 2000, "origin": "AUS" }
]
const sorted = arr.sort((a,b) => a.type.localeCompare(b.type, undefined, {sensitivity:'accent'}) || a.year - b.year)
console.log(sorted)
If you do one sort followed by a different sort, the final sort overrides any previous sort.
Combine them into the same lambda
json.sort( ( a, b ) => {
aType = a.type.toLowerCase();
bType = b.type.toLowerCase();
aYear = a.year;
bYear = b.year;
return aType < bType
? -1
: aType > bType
? 1
: aYear < bYear
? -1
: aYear > bYear
? 1
: 0;
})
Though this has gotten pretty unreadable. You can have multiple comparison functions:
let compareByType = (a, b) => {
aType = a.type.toLowerCase();
bType = b.type.toLowerCase();
return (aType<bType) ? -1 : (aType>bType ? 1 : 0);
}
let compareByYear = (a,b) => {
return a.year - b.year;
}
json.sort(
(a, b) => {
let s = compareByType(a, b);
if(s !== 0) {
return s;
} else {
return compareByYear(a, b);
}
}
);
You can do this with one sort by first checking if the types are equal. If so, sort on the date. If not, sort on the type.
const json = [
{ "type": "car", "year": 2007, "origin": "AUS" },
{ "type": "truck", "year": 2021, "origin": "USA" },
{ "type": "car", "year": 2004, "origin": "CA" },
{ "type": "bike", "year": 2016, "origin": "UK" },
{ "type": "truck", "year": 2020, "origin": "CA" },
{ "type": "bike", "year": 2000, "origin": "AUS" }
]
// one after other
json.sort( ( a, b ) => {
a = a.type.toLowerCase();
b = b.type.toLowerCase();
if (a === b) {
return a.year - b.year;
}
return a < b ? -1 : 1;
});
console.log(json);
Related
I have a array like this in below, What I'm trying is seperating objects to new array by grouping two values.
Array:
[
{
"year": "202003",
"cost": 11194.55,
"type": "A"
},
{
"year": "202003",
"cost": 60.2,
"type": "B"
},
{
"year": "202003",
"cost": 747.12,
"type": "C"
},
{
"year": "202003",
"cost": 747.12,
"type": "D"
},
{
"year": "202004",
"cost": 747.12,
"type": "D"
},
{
"year": "202003",
"cost": 4674.59,
"type": "D"
}
]
Result should be like this;
Output
[
[
{
"year": "202003",
"cost": 11194.55,
"type": "A"
}
],
[
{
"year": "202003",
"cost": 60.2,
"type": "B"
}
],
[
{
"year": "202003",
"cost": 747.12,
"type": "C"
}
],
[
{
"year": "202003",
"cost": 1494.24, // sum of the COST value when year and type same.
"type": "D"
},
{
"year": "202004",
"cost": 4674.59,
"type": "D"
}
]
];
What I've tried
<script src="//cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.min.js"></script>
let aggregatedObject = Enumerable.From(data)
.GroupBy("$.type", "$.year",
function (key, g) {
return {
label: key,
value: g.Sum("$.cost"),
}
})
.ToArray();
How can I group this data like this? Is there any library or a function to do this? I couldn't find yet.
Any help will be highly appreciated!
Looking at your initial array and the output you wanted to get, below are the examples that result in exactly the same structure as per your question - an array of arrays of objects
One way with find & for of loop:
let arr = [
{
"year": "202003",
"cost": 11194.55,
"type": "A"
},
{
"year": "202003",
"cost": 60.2,
"type": "B"
},
{
"year": "202003",
"cost": 747.12,
"type": "C"
},
{
"year": "202003",
"cost": 747.12,
"type": "D"
},
{
"year": "202004",
"cost": 747.12,
"type": "D"
},
{
"year": "202003",
"cost": 4674.59,
"type": "D"
}
]
let sortedArray = []
for (let [index, el] of arr.entries()) {
if(sortedArray.find(elInner => (elInner[0].type === el.type && elInner[0].year !== el.year))) {
sortedArray.find(elInner => elInner[0].type === el.type).push(arr[index])
}else if (sortedArray.find(elInner => (elInner[0].type === el.type && elInner[0].year == el.year))) {
sortedArray.find(elInner => (elInner[0].type === el.type && elInner[0].year == el.year))[0].cost += arr[index].cost
}else {
sortedArray.push([el])
}
}
console.log(sortedArray)
and another "cleaner" way with reduce & map
let arr = [
{
"year": "202003",
"cost": 11194.55,
"type": "A"
},
{
"year": "202003",
"cost": 60.2,
"type": "B"
},
{
"year": "202003",
"cost": 747.12,
"type": "C"
},
{
"year": "202003",
"cost": 747.12,
"type": "D"
},
{
"year": "202004",
"cost": 747.12,
"type": "D"
},
{
"year": "202003",
"cost": 4674.59,
"type": "D"
}
]
let sortedArray = arr.reduce((acc, obj) => {
const key = obj.type, year = obj.year
!!acc[key]
? (!!acc[key][year] ? acc[key][year].cost += obj.cost : acc[key][year] = obj)
: (acc[key] = [], acc[key][year] = obj)
return acc
}, [])
sortedArray = Object.values(sortedArray).map((val) => Object.values(val))
console.log(sortedArray)
You can use Array.reduce in order to accumulate the cost.
const data = [
{
year: '202003',
cost: 11194.55,
type: 'A',
},
{
year: '202003',
cost: 60.2,
type: 'B',
},
{
year: '202003',
cost: 747.12,
type: 'C',
},
{
year: '202003',
cost: 747.12,
type: 'D',
},
{
year: '202004',
cost: 747.12,
type: 'D',
},
{
year: '202003',
cost: 4674.59,
type: 'D',
},
];
const final = data.reduce((result, current) => {
const key = `${current.year}-${current.type}`;
result[key] = result[key] || {...current, cost: 0};
result[key].cost += current.cost;
return result;
}, {});
console.log(Object.values(final).map(item => ([item])));
You can try to use array.reduce instead of linq.js, every callback execution accumulates the data if there's matching year and type or adds a copy of an object to an array which is returned from the function:
let data = [
{
"year": "202003",
"cost": 11194.55,
"type": "A"
},
{
"year": "202003",
"cost": 60.2,
"type": "B"
},
{
"year": "202003",
"cost": 747.12,
"type": "C"
},
{
"year": "202003",
"cost": 747.12,
"type": "D"
},
{
"year": "202004",
"cost": 747.12,
"type": "D"
},
{
"year": "202003",
"cost": 4674.59,
"type": "D"
}
];
let aggregatedObject = data.reduce((acc,cur) => {
let prev = acc.find(x => x.year === cur.year && x.type === cur.type);
if(!prev){
acc.push([{...cur}]);
} else {
prev.cost += cur.cost;
}
return acc;
}, []);
console.log(aggregatedObject);
You could take a joined key with linq as forth parameter and a combined object for getting a summed value.
var data = [{ year: "202003", cost: 11194.55, type: "A" }, { year: "202003", cost: 60.2, type: "B" }, { year: "202003", cost: 747.12, type: "C" }, { year: "202003", cost: 747.12, type: "D" }, { year: "202004", cost: 747.12, type: "D" }, { year: "202003", cost: 4674.59, type: "D" }],
result = Enumerable
.From(data)
.GroupBy(
null,
null,
"{ year: $.year, cost: $$.Sum('$.cost'), type: $.type }",
"$.year + '|' + $.type"
)
.ToArray();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/linq.js/2.2.0.2/linq.js"></script>
I've got the following JSON:
var obj =
{
"workers": [
{
"TimeStamp": "2020-03-13T10:08",
"Status": "status1",
"Name": "one",
"Number": 19.9
},
{
"TimeStamp": "2019-07-19T06:01",
"Status": "status2",
"Name": "one",
"Number": 9
},
{
"TimeStamp": "2020-04-22T05:10",
"Status": "status2",
"Name": "one",
"Number": 10.1
},
{
"TimeStamp": "2019-07-21T23:53",
"Status": "status2",
"Name": "two",
"Number": 16.3
},
{
"TimeStamp": "2019-11-21T05:14",
"Status": "status1",
"Name": "three",
"Number": 122.54
},
...
]
};
As you see there's just 2 different status possible: "status1" and "status2".
Names should be filtered to be shown just once, but combine the two different status.
The respective status should include the "TimeStamp" and "Number" in an array.
In the end it should look like this:
{
"workers": [
{
"Name":"one",
"status1": [
{
"TimeStamp":"2020-03-13T10:08",
"Number": 19.9
}
],
"status2": [
{
"TimeStamp":"2019-07-19T06:01",
"Number": 9
},
{
"TimeStamp": "2020-04-22T05:10",
"Number": 10.1
},
]
},
{
"Name":"two",
"status1": [],
"status2": [
{
"TimeStamp":"2019-07-21T23:53",
"Number": 16.3
}
]
},
{
"Name":"three",
"status1": [
{
"TimeStamp":"2019-11-21T05:14",
"Number": 122.54
}
],
"status2": []
}
]
}
I tried out the following so far:
var writeObj = { 'workers': [] };
for (var i = 0; i < obj.workers.length; i++) {
if(!Object.values(writeObj.workers).includes(obj.workers[i].Name)) {
writeObj['workers'].push({ Name: obj.workers[i].Name, 'status1': [], 'status2': [] });
for (var j = 0; j < obj.workers.length; j++) {
if (obj.workers[j].Name === obj.workers[i].Name && obj.workers[j].Status === 'status1') {
writeObj['workers'][i]['status1'].push({ TimeStamp: obj.workers[j].TimeStamp, Number: obj.workers[j].Number });
} else if (obj.workers[j].Name === obj.workers[i].Name && obj.workers[j].Status === 'status2') {
writeObj['workers'][i]['status2'].push({ TimeStamp: obj.workers[j].TimeStamp, Number: obj.workers[j].Number });
}
}
}
}
I'm stuck and can't see the mistake...
Thanks for any help!
You can aggregate your data using array.reduce:
var obj =
{
"workers": [
{
"TimeStamp": "2020-03-13T10:08",
"Status": "status1",
"Name": "one",
"Number": 19.9
},
{
"TimeStamp": "2019-07-19T06:01",
"Status": "status2",
"Name": "one",
"Number": 9
},
{
"TimeStamp": "2020-04-22T05:10",
"Status": "status2",
"Name": "one",
"Number": 10.1
},
{
"TimeStamp": "2019-07-21T23:53",
"Status": "status2",
"Name": "two",
"Number": 16.3
},
{
"TimeStamp": "2019-11-21T05:14",
"Status": "status1",
"Name": "three",
"Number": 122.54
}
]
};
let output = obj.workers.reduce((acc,cur) => {
let {Name, Status, ...rest} = cur;
let match = acc.find(x => x.Name === Name);
if(!match){
match = { Name: Name };
acc.push(match);
}
if(!match[Status]){
match[Status] = [];
}
match[Status].push(rest);
return acc;
}, []);
console.log({workers: output});
You can use Array#reduce. Group by the Name key according to your format, then take the grouped values as the result. Time complexity is O(n).
var obj = { "workers": [ { "TimeStamp": "2020-03-13T10:08", "Status": "status1", "Name": "one", "Number": 19.9 }, { "TimeStamp": "2019-07-19T06:01", "Status": "status2", "Name": "one", "Number": 9 }, { "TimeStamp": "2020-04-22T05:10", "Status": "status2", "Name": "one", "Number": 10.1 }, { "TimeStamp": "2019-07-21T23:53", "Status": "status2", "Name": "two", "Number": 16.3 }, { "TimeStamp": "2019-11-21T05:14", "Status": "status1", "Name": "three", "Number": 122.54 }, ] };
const grouped = Object.values(obj.workers.reduce((a, e) => {
if (!a[e.Name]) {
a[e.Name] = {Name: e.Name, status1: [], status2: []};
}
a[e.Name][e.Status].push({TimeStamp: e.TimeStamp, Number: e.Number});
return a;
}, {}));
console.log(grouped);
I want to filter the items array objects which match the "model" key in the models array and store them in an array. I did succeed in my attempt but I am not very satisfied with my effort. Are there any better ways of doing it?
Any suggestions on how to do it using underscore.js and lodash? Or using the native javascript map and filter functions?
The JSON object
{
"items": [
{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
],
"models": [
{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
]
}
My Solution
const { models, items } = jsonData;
const newarray = [];
for(let i = 0; i < models.length; i++) {
for(let j = 0; j < items.length; j++) {
if(items[j].model===models[i].model) {
let obj = {
...items[j],
year: models[i].year
}
newarray.push(obj);
}
}
}
I would take a slightly different approach. I guess you might like it.
const models = [
{
"model": "ruie9",
"year": 1998
},
{
"model": "not-found",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
];
const items = [
{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
];
const transformed = models.reduce((res, val) => {
res[val.model] = val;
return res;
}, {}); // Transform models into a dictionary.
const filtered = items.filter(i => i.model in transformed);
console.log(filtered);
You could do this:
I thought you wanted to add the year from models array too.
If so, look at this implementation. This is more efficient O(n) than O(n*n) solution that you attempted earlier. For large arrays O(n*n) is not preferred.
let items = [{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
];
let models = [
{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
}
];
let objModels = models.reduce(function(r,v) {
r[v.model] = v;
return r;
}, {});
let objItems = items.reduce(function(r,v) {
r[v.model] = v;
return r;
}, {});
let ans = [];
for(let key in objItems) {
if(key in objModels) {
let o = objItems[key];
o.year = objModels[key].year;
ans.push(o);
}
}
console.log(ans);
You can rewrite
let obj = {
...items[j],
year: models[i].year
}
as
let obj = Object.assign({}, items[j], { year: models[i].year });
And you can also use Array.prototype.forEach instead of a for loop, like so
models.forEach((m) => {
items.forEach((i) => {
if (m.id === i.id) {
let obj = Object.assign({}, i, { year: m.year });
newArray.push(obj);
}
})
})
I tried to keep it as similar to your solution as possible.
Try this snippet:
const jsonData = {
"items": [{
"model": "ooc0d",
"code": "2x4qr",
"price": 33
},
{
"model": "ruie9",
"code": "2f6gi",
"price": 22
},
{
"model": "aqu0d",
"code": "2f6gi",
"price": 21
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 25
},
{
"model": "ddebd",
"code": "2f6gi",
"price": 29
}
],
"models": [{
"model": "ruie9",
"year": 1998
},
{
"model": "ooc0d",
"year": 1991
},
{
"model": "aqu0d",
"year": 1994
},
{
"model": "ddebd",
"year": 1995
},
{
"model": "odq76",
"year": 1999
}
]
};
var newArray = jsonData.models.reduce(
(acc, modelData) => {
let filteredItems = jsonData.items.filter(item => item.model === modelData.model);
if (filteredItems.length) {
acc.push(...filteredItems);
}
return acc;
}, [])
console.log(newArray);
Here is my JSON code. I'm storing this json in an array.
{
"kind": "urlshortener#url",
"id": "http://goo.gl/2FIrtF",
"longUrl": "http://hike.com/?utm_source=facebook",
"status": "OK",
"created": "2015-09-22T13:45:53.645+00:00",
"analytics": {
"allTime": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"month": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"week": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"day": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
},
"twoHours": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
}
},
"result": {
"kind": "urlshortener#url",
"id": "http://goo.gl/2FIuvF",
"longUrl": "http://hike.com/?utm_source=facebook",
"status": "OK",
"created": "2015-09-22T13:45:53.645+00:00",
"analytics": {
"allTime": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"month": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"week": {
"shortUrlClicks": "1",
"longUrlClicks": "1",
"referrers": [
{
"count": "1",
"id": "unknown"
}
],
"countries": [
{
"count": "1",
"id": "IN"
}
],
"browsers": [
{
"count": "1",
"id": "Chrome"
}
],
"platforms": [
{
"count": "1",
"id": "Macintosh"
}
]
},
"day": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
},
"twoHours": {
"shortUrlClicks": "0",
"longUrlClicks": "0"
}
}
}
}
In the above JSON, how can we get the existence of analytics -> day -> countries?
I want to know whether the countries exists in day or not first, if it's not, show some value. If it is there, it will try to fetch the count of particualr country.
I'm trying this from last 5 hours without any luck.
if(arr.analytics.day.countries !== undefined) {
function thingscount(arr, platf) {
var x = arr.analytics.day.countries.map(function(el) {
return (platf.indexOf(el.id) != -1) ? parseInt(el.count) : 0; });
var count = 0;
for (var i = 0; i < x.length; i++) count += x[i];
return count;
}
var one = thingscount(arr, ["US"]);
}else{
var one = 0;
}
The above code is working fine if there is countries in day, but sometimes, in my JSON there will be no platforms part, in that case it's giving me
Uncaught TypeError: Cannot read property 'map' of undefined
I need a way to check if the platforms exist, if it's go for a count, if it's not give some other value to the variable.
UPDATE :
I'm using this below code to get the count of IN.
When it has IN key and value, it's giving me the result. But when it don't has the IN key, it's showing 'undefined count' error.
var month_inclicks = arr.analytics.month.countries.filter(function(el) { return el.id == "IN"; })[0].count;
How can we set a default value if the key we are looking for is not exists?
While that isn't JSON, I'm assuming it's a javascript object. That being said, you'll want to look into utilizing the hasOwnProperty method or the in keyword.
Example:
if (arr.total.limited.hasOwnProperty('platforms')) { //do stuff
or
if ('platforms' in arr.total.limited) { //do something
I have corrected your JSON. use hasOwnProperty as #CollinD suggested
var arr = {
total: {
limited: {
things: "451",
platforms: [{
count: "358",
id: "Windows"
}, {
count: "44",
id: "X11"
}, {
count: "42",
id: "Macintosh"
}, {
count: "2",
id: "Linux"
}, {
count: "1",
id: "iPhone"
}, {
count: "1",
id: "iPod"
}]
}
}
};
Object.prototype.hasOwnProperty()
console.log(arr.total.limited.hasOwnProperty('platforms'));
DEMO
For the record, you can roll the map and the count in your 'thingscount' function into one operation by using reduce:
var getCount = function getCount( ary, find ) {
return ary.reduce(function ( acc, record) {
if (find.indexOf(record.id) !== -1) acc += parseInt(record.count, 10);
return acc;
}, 0);
};
Usage inline:
if (arr.analytics.day.hasOwnProperty('countries')) {
var find = ['IN'],
count = arr.analytics.day.countries.reduce(function ( acc, record) {
if (find.indexOf(record.id) !== -1) acc += parseInt(record.count, 10);
return acc;
}, 0);
}
Or with the function:
if (arr.analytics.day.hasOwnProperty('countries')) {
var count = getCount(arr.analytics.day.countries, ['US','IN']);
}
What i need to do here is whenever i call a method say for campaign data it needs to go to "name" : "campaign " and give me "values" in this format
{"car":"car",
"bus":"bus",
"truck":"truck",
"train":"train"}
in the same way i need for sub campaign . (Comment if anything is unclear)
{
"fields": [
{
"name": "campaign",
"default": "",
"values": [
"car",
"bus",
"truck",
"train"
]
},
{
"name": "subCampaign",
"default": "",
"values": [
"Spring 2015",
"BTS 2015",
"BTS 2014",
"Holiday 2015",
"Holiday 2014"
]
},
]
}
If we have
var obj ={
"fields": [
{
"name": "campaign",
"default": "",
"values": [
"car",
"bus",
"truck",
"train"
]
},
{
"name": "subCampaign",
"default": "",
"values": [
"Spring 2015",
"BTS 2015",
"BTS 2014",
"Holiday 2015",
"Holiday 2014"
]
},
]
};
You can do it like this, say for `campaign, you can use:
var result = {};
obj.fields[0].values.forEach(function(val){
result[val] = val
});
This would give result as object having value : {car: "car", bus: "bus", truck: "truck", train: "train"}
Assuming you want {"car":"car", "bus":"bus","truck":"truck","train":"train"}
var object = {
"fields": [{
"name": "campaign",
"default": "",
"values": [
"car",
"bus",
"truck",
"train"]
},
{
"name": "subCampaign",
"default": "",
"values": [
"Spring 2015",
"BTS 2015",
"BTS 2014",
"Holiday 2015",
"Holiday 2014"]
}, ]
};
var passingObj = object.fields[0].values;
alert(JSON.stringify(getObj(passingObj)));
function getObj(passingObj) {
var obj = {};
for (var index in passingObj) {
obj[passingObj[index]] = passingObj[index];
}
return obj;
}