Related
I have an array like below and need to transform this array with sub arrays
[{
author: " "
category: "test1"
date: "8 September 2020"
extension: null
id: 5
maintitle: "test"
siteName: "site1"
title: "test1"
url: ""
},
{
author: ""
category: "test1"
date: "10 September 2020"
extension: null
id: 4
maintitle: "test2"
siteName: "site1"
title: "test2"
url: ""
},
{
author: " "
category: "test3"
date: "2 September 2020"
extension: null
id: 1
maintitle: "test3"
siteName: "Site3"
title: "test3"
url: ""
}]
The output would look like this:
[{
id: 1,
date: "8 September 2020",
title: test1,
category: test1,
"files": {
"Site1": [{
author: " "
date: "8 September 2020",
extension: null,
title: "test1"
}, {
author: " ",
date: "10 September 2020"
extension: null,
title: "test2"
url: ""
}
]
}
},
[{
id: 2,
date: "8 September 2020",
title: "test3",
category: "test3",
"files": {
"site3": [{
author: " ",
date: "30 August 2020",
extension: null,
title: "test3",
url: ""
}]
}]
}]
Groupby need to do with sitename and Category using Jquery/javascript. Please help me on this. Any help is much appreciated.
You could take an array for the wanted groups and an iterative approach for the nested arrays.
const
data = [{ author: "Merin", category: "Forms", date: "8 September 2020", documentName: "Credit1 Forms", documentUrl: "", id: 5, siteName: "Credit", title: "Forms" }, { author: "Sandeep", category: "Forms", date: "10 September 2020", documentName: "AFAD1 Forms", documentUrl: "#", id: 4, siteName: "Credit", title: "Forms" }, { author: "Jithin", category: "Policies", date: "2 September 2020", documentName: "Credit1 Manuel", documentUrl: "#", id: 1, siteName: "Credit", title: "Policies" }],
groups = [['category', 'files'], ['siteName']],
result = data.reduce((r, o) => {
groups
.reduce((p, [key, children = o[key]], i) => {
let value, group;
({ [key]: value, ...o } = o);
group = p.find(g => g[key] === value);
if (!group) p.push(group = { ...(i === 0 ? { id: p.length + 1 } : {}), [key]: value, [children]: [] });
return group[children];
}, r)
.push(o);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
What is the most concise and efficient way to find out if a JavaScript array contains duplicates and merge them into new array please ?
I tried Lodash / d3 / underscoreJs but none of them generate clean result so I tried this code ->
var arr = [
{
"title": "My unique title",
"link": "domainlinkto-my-unique-title",
"image": "someurlto/my-unique-title-image",
"date": "Mon, 29 Jul 2019 02:25:08 -0000",
"site": "site1"
},
{
"title": "A duplicate title",
"link": "somedomainlinkto-a-duplicate-title/",
"image": "randomurlto/a-duplicate-title.jpg",
"date": "Sun, 25 Aug 2019 15:52:59 -0000",
"site": "site1"
},
{
"title": "A duplicate title",
"link": "otherdomainlinkto-a-duplicate-title/",
"image": "anotherurlto/duplicate-title.jpg",
"date": "Sun, 25 Aug 2019 21:09:37 -0000",
"site": "site2"
},
{
"title": "A DUPLICATE TITLE",
"link": "someotherdomainlinkto-a-duplicate-title/",
"image": "someurlto/aduplicatetitle.jpg",
"date": "Sat, 24 Aug 2019 18:43:38 -0000",
"site": "site3"
},
{
"title": "Other duplicate: title",
"link": "anydomainlinkto-other-duplicate-title/",
"image": "anotherdomainurlto/other-duplicate-title.jpg",
"date": "Mon, 26 Aug 2019 00:37:28 -0000",
"site": "site2"
},
{
"title": "Other duplicate : title",
"link": "anyotherdomainlinkto-other-duplicate-title/",
"image": "exampleurlto/hjKGHK45huu.jpg",
"date": "Mon, 26 Aug 2019 00:37:28 -0000",
"site": "site5"
},
{
"title": "Other unique title",
"link": "anydomainlinkto-other-unique-title/",
"image": "anyotherurlto/img/other-title.jpg",
"date": "Mon, 26 Aug 2019 09:18:10 -0000",
"site": "site3"
}
];
Array.prototype.groupBy = function (props) {
var arr = this;
var partialResult = {};
var imgResult = {};
arr.forEach(el=>{
var grpObj = {};
var grpImg = {};
props.forEach(prop=>{
grpObj.title = el.title;
grpImg.image = el.image;
});
var key = JSON.stringify(grpObj);
var keyImg = JSON.stringify(grpImg);
if(!imgResult[key]) {
imgResult[key] = grpImg.image;
} else {
imgResult[key] = el.image;
}
if(!partialResult[key]) partialResult[key] = [];
partialResult[key].push(
{
link: el.link,
site: el.site,
date: el.date
});
});
var finalResult = Object.keys(partialResult, imgResult).map(key=>{
var keyObj = JSON.parse(key);
keyObj.links = partialResult[key];
keyObj.image = imgResult[key];
return keyObj;
})
return finalResult;}
var filtered = arr.groupBy(['title']);
console.log(filtered);
BUT...
As you can see [titles] in UPPERCASE and "Other duplicate : title" is not taken as duplicate
WHAT I WOULD DO --->
var expected = [
{
"title": "My unique title",
"links": [{"date": "Mon, 29 Jul 2019 02:25:08 -0000","site": "site1", "link": "domainlinkto-my-unique-title"}],
"image": "someurlto/my-unique-title-image",
},
{
"title": "My duplicate title",
"links": [
{"date": "Sun, 25 Aug 2019 15:52:59 -0000","site": "site1","link":"somedomainlinkto-a-duplicate-title/"},
{"date": "Sun, 25 Aug 2019 21:09:37 -0000","site": "site2","link": "otherdomainlinkto-a-duplicate-title/"},
{"date": "Sat, 24 Aug 2019 18:43:38 -0000","site": "site3","link": "someotherdomainlinkto-a-duplicate-title/"}
],
"image": "randomurlto/a-duplicate-title.jpg",
},
{
"title": "Other duplicate: title",
"links": [
{"date": "Sun, 25 Aug 2019 15:52:59 -0000","site": "site2","link":"anydomainlinkto-other-duplicate-title/"},
{"date": "Mon, 26 Aug 2019 00:37:28 -0000","site": "site5","link": "anyotherdomainlinkto-other-duplicate-title/"}
],
"image": "anotherdomainurlto/other-duplicate-title.jpg",
},
{
"title": "Other unique title",
"links": [{"date": "Mon, 26 Aug 2019 09:18:10 -0000","site": "site1", "link": "anydomainlinkto-other-unique-title/"}],
"image": "anyotherurlto/img/other-title.jpg",
"site": "site3"
}
];
console.log(expected);
Hi Genious
What is the most concise and efficient way to find out if a JavaScript array contains duplicates and merge them into new array please ?
I tried Lodash / d3 / underscoreJs but none of them generate clean result so I tried this code ->
var arr = [
{
"title": "My unique title",
"link": "domainlinkto-my-unique-title",
"image": "someurlto/my-unique-title-image",
"date": "Mon, 29 Jul 2019 02:25:08 -0000",
"site": "site1"
},
{
"title": "A duplicate title",
"link": "somedomainlinkto-a-duplicate-title/",
"image": "randomurlto/a-duplicate-title.jpg",
"date": "Sun, 25 Aug 2019 15:52:59 -0000",
"site": "site1"
},
{
"title": "A duplicate title",
"link": "otherdomainlinkto-a-duplicate-title/",
"image": "anotherurlto/duplicate-title.jpg",
"date": "Sun, 25 Aug 2019 21:09:37 -0000",
"site": "site2"
},
{
"title": "A DUPLICATE TITLE",
"link": "someotherdomainlinkto-a-duplicate-title/",
"image": "someurlto/aduplicatetitle.jpg",
"date": "Sat, 24 Aug 2019 18:43:38 -0000",
"site": "site3"
},
{
"title": "Other duplicate: title",
"link": "anydomainlinkto-other-duplicate-title/",
"image": "anotherdomainurlto/other-duplicate-title.jpg",
"date": "Mon, 26 Aug 2019 00:37:28 -0000",
"site": "site2"
},
{
"title": "Other duplicate : title",
"link": "anyotherdomainlinkto-other-duplicate-title/",
"image": "exampleurlto/hjKGHK45huu.jpg",
"date": "Mon, 26 Aug 2019 00:37:28 -0000",
"site": "site5"
},
{
"title": "Other unique title",
"link": "anydomainlinkto-other-unique-title/",
"image": "anyotherurlto/img/other-title.jpg",
"date": "Mon, 26 Aug 2019 09:18:10 -0000",
"site": "site3"
}
];
Array.prototype.groupBy = function (props) {
var arr = this;
var partialResult = {};
var imgResult = {};
arr.forEach(el=>{
var grpObj = {};
var grpImg = {};
props.forEach(prop=>{
grpObj.title = el.title;
grpImg.image = el.image;
});
var key = JSON.stringify(grpObj);
var keyImg = JSON.stringify(grpImg);
if(!imgResult[key]) {
imgResult[key] = grpImg.image;
} else {
imgResult[key] = el.image;
}
if(!partialResult[key]) partialResult[key] = [];
partialResult[key].push(
{
link: el.link,
site: el.site,
date: el.date
});
});
var finalResult = Object.keys(partialResult, imgResult).map(key=>{
var keyObj = JSON.parse(key);
keyObj.links = partialResult[key];
keyObj.image = imgResult[key];
return keyObj;
})
return finalResult;}
var filtered = arr.groupBy(['title']);
console.log(filtered);
BUT...
As you can see [titles] in UPPERCASE and "Other duplicate : title" is not taken as duplicate
WHAT I WOULD DO --->
[
{
"title": "My unique title",
"links": [{"date": "Mon, 29 Jul 2019 02:25:08 -0000","site": "site1", "link": "domainlinkto-my-unique-title"}],
"image": "someurlto/my-unique-title-image",
},
{
"title": "My duplicate title",
"links": [
{"date": "Sun, 25 Aug 2019 15:52:59 -0000","site": "site1","link":"somedomainlinkto-a-duplicate-title/"},
{"date": "Sun, 25 Aug 2019 21:09:37 -0000","site": "site2","link": "otherdomainlinkto-a-duplicate-title/"},
{"date": "Sat, 24 Aug 2019 18:43:38 -0000","site": "site3","link": "someotherdomainlinkto-a-duplicate-title/"}
],
"image": "randomurlto/a-duplicate-title.jpg",
},
{
"title": "Other duplicate: title",
"links": [
{"date": "Sun, 25 Aug 2019 15:52:59 -0000","site": "site2","link":"anydomainlinkto-other-duplicate-title/"},
{"date": "Mon, 26 Aug 2019 00:37:28 -0000","site": "site5","link": "anyotherdomainlinkto-other-duplicate-title/"}
],
"image": "anotherdomainurlto/other-duplicate-title.jpg",
},
{
"title": "Other unique title",
"links": [{"date": "Mon, 26 Aug 2019 09:18:10 -0000","site": "site1", "link": "anydomainlinkto-other-unique-title/"}],
"image": "anyotherurlto/img/other-title.jpg",
"site": "site3"
}
];
I'm sure this is not the better way to do that (we are agree) so I'm asking stackoverflow genious...
Thanks for reading and time spent for thinking about my problem
I'd just lowercase the title before building up the json object for grouping. And I'd use object destructuring to clean up things, as well as just one hashtable, and I don't see the sense in a generic Array.prototype.groupBy if you hardcode properties in it:
const hash = {}, result = [];
for(const { title, link, image, date, site } of input) {
const key = JSON.stringify({ title: title.toLowerCase().replace(/ /g, ""), });
if(hash[key]) {
hash[key].push({ link, date, site });
} else {
result.push({ title, image, links: hash[key] = [{ link, date, site }], });
}
}
Seems like you want to group by lowercase titles without spaces :
var arr = [{"title":"My unique title","link":"domainlinkto-my-unique-title","image":"someurlto/my-unique-title-image","date":"Mon, 29 Jul 2019 02:25:08 -0000","site":"site1"},{"title":"A duplicate title","link":"somedomainlinkto-a-duplicate-title/","image":"randomurlto/a-duplicate-title.jpg","date":"Sun, 25 Aug 2019 15:52:59 -0000","site":"site1"},{"title":"A duplicate title","link":"otherdomainlinkto-a-duplicate-title/","image":"anotherurlto/duplicate-title.jpg","date":"Sun, 25 Aug 2019 21:09:37 -0000","site":"site2"},{"title":"A DUPLICATE TITLE","link":"someotherdomainlinkto-a-duplicate-title/","image":"someurlto/aduplicatetitle.jpg","date":"Sat, 24 Aug 2019 18:43:38 -0000","site":"site3"},{"title":"Other duplicate: title","link":"anydomainlinkto-other-duplicate-title/","image":"anotherdomainurlto/other-duplicate-title.jpg","date":"Mon, 26 Aug 2019 00:37:28 -0000","site":"site2"},{"title":"Other duplicate : title","link":"anyotherdomainlinkto-other-duplicate-title/","image":"exampleurlto/hjKGHK45huu.jpg","date":"Mon, 26 Aug 2019 00:37:28 -0000","site":"site5"},{"title":"Other unique title","link":"anydomainlinkto-other-unique-title/","image":"anyotherurlto/img/other-title.jpg","date":"Mon, 26 Aug 2019 09:18:10 -0000","site":"site3"}]
var result = arr.reduce((o, { title, image, link, date, site }, k) => (
( o[k = title.toLowerCase().replace(/ /g, '')] = o[k] || { title, image, links: [] } )
.links.push({ date, site, link }), o), {})
console.log( Object.values(result) )
If it has to work in IE too :
var arr = [{"title":"My unique title","link":"domainlinkto-my-unique-title","image":"someurlto/my-unique-title-image","date":"Mon, 29 Jul 2019 02:25:08 -0000","site":"site1"},{"title":"A duplicate title","link":"somedomainlinkto-a-duplicate-title/","image":"randomurlto/a-duplicate-title.jpg","date":"Sun, 25 Aug 2019 15:52:59 -0000","site":"site1"},{"title":"A duplicate title","link":"otherdomainlinkto-a-duplicate-title/","image":"anotherurlto/duplicate-title.jpg","date":"Sun, 25 Aug 2019 21:09:37 -0000","site":"site2"},{"title":"A DUPLICATE TITLE","link":"someotherdomainlinkto-a-duplicate-title/","image":"someurlto/aduplicatetitle.jpg","date":"Sat, 24 Aug 2019 18:43:38 -0000","site":"site3"},{"title":"Other duplicate: title","link":"anydomainlinkto-other-duplicate-title/","image":"anotherdomainurlto/other-duplicate-title.jpg","date":"Mon, 26 Aug 2019 00:37:28 -0000","site":"site2"},{"title":"Other duplicate : title","link":"anyotherdomainlinkto-other-duplicate-title/","image":"exampleurlto/hjKGHK45huu.jpg","date":"Mon, 26 Aug 2019 00:37:28 -0000","site":"site5"},{"title":"Other unique title","link":"anydomainlinkto-other-unique-title/","image":"anyotherurlto/img/other-title.jpg","date":"Mon, 26 Aug 2019 09:18:10 -0000","site":"site3"}];
var result = arr.reduce(function(o, v) {
var key = v.title.replace(/ /g, '').toLowerCase();
if (!o[key]) o[key] = { title: v.title, image: v.image, links: [] };
o[key].links.push({ date: v.date, site: v.site, link: v.link });
return o;
}, {});
console.log( Object.keys(result).map(function(k) { return result[k]; }) );
I want to use a JSON object to build a datatable, but I receive the following error:
after that, the browser shows :
I was trying by hours everthing that the url in the warning message says.. but i didnt figure out.
The JSON object is retrieved by a servlet named MyJson. This JSon has the following appareance.
{
"data":[
["NAME: Name1","DIRECTION: Salida","CHARGED: 15","AFFORDED: 15"],
["NAME: Name2","DIRECTION: Salida","CHARGED: 4","AFFORDED: 4"],
["NAME: Name3","DIRECTION: Entrada","CHARGED: 4","AFFORDED: 4"],
["NAME: Name4","DIRECTION: Salida","CHARGED: 1","AFFORDED: 0"],
["NAME: Name5","DIRECTION: Entrada","CHARGED: 15","AFFORDED: 15"],
["NAME: Name6","DIRECTION: Entrada","CHARGED: 10","AFFORDED: 10"],
["NAME: Name7","DIRECTION: Entrada","CHARGED: 15","AFFORDED: 15"],
["NAME: Name8","DIRECTION: Entrada","CHARGED: 3","AFFORDED: 3"],
["NAME: Name9","DIRECTION: Entrada","CHARGED: 15","AFFORDED: 15"]
]
}
And this is my javascript
<script>
$(document).ready(function() {
var tableEntityList = $('#testable').DataTable({
"processing": true,
"scrollY":"500px",
"scrollCollapse": true,
"paging":false,
"serverSide":true,
"ajax":"./MyJson",
"columns": [
{ "data":'NAME' },
{ "data":'DIRECTION' },
{ "data":'CHARGED' },
{ "data":'AFFORDED' }
]
});
})
</script>
<body>
<table class="display responsive nowrap" id="testable" cellspacing="0">
<thead>
<th>NAME</th>
<th>DIRECTION</th>
<th>CHARGED</th>
<th>AFFORDED</th>
</thead>
<tbody>
</tbody>
</table>
Can you tell me what am i doing wrong?
Thank you.
You'll need to process your data before passing it to DataTables and you can do this within dataSrc. Check this JSFiddle:
let jsonData = {
"data": [
["NAME: Name1", "DIRECTION: Salida", "CHARGED: 15", "AFFORDED: 15"],
["NAME: Name2", "DIRECTION: Salida", "CHARGED: 4", "AFFORDED: 4"],
["NAME: Name3", "DIRECTION: Entrada", "CHARGED: 4", "AFFORDED: 4"],
["NAME: Name4", "DIRECTION: Salida", "CHARGED: 1", "AFFORDED: 0"],
["NAME: Name5", "DIRECTION: Entrada", "CHARGED: 15", "AFFORDED: 15"],
["NAME: Name6", "DIRECTION: Entrada", "CHARGED: 10", "AFFORDED: 10"],
["NAME: Name7", "DIRECTION: Entrada", "CHARGED: 15", "AFFORDED: 15"],
["NAME: Name8", "DIRECTION: Entrada", "CHARGED: 3", "AFFORDED: 3"],
["NAME: Name9", "DIRECTION: Entrada", "CHARGED: 15", "AFFORDED: 15"]
]
};
$(document).ready(function() {
var tableEntityList = $('#testable').DataTable({
"processing": true,
"scrollY": "500px",
"scrollCollapse": true,
"paging": false,
"ajax": {
type: 'POST',
dataType: 'json',
url: '/echo/json/',
data: {
json: JSON.stringify(jsonData)
},
dataSrc: function(json) {
var properData = [];
$.each(json.data, function(k, v) {
var returnObject = {};
$.each(v, function(a, b) {
var elArr = b.split(":");
returnObject[elArr[0].trim()] = elArr[1].trim()
});
properData.push(returnObject)
});
return properData;
}
},
"columns": [{
"data": 'NAME'
}, {
"data": 'DIRECTION'
}, {
"data": 'CHARGED'
}, {
"data": 'AFFORDED'
}]
});
});
Please note though that serverSide will not work!
If you use columns.data, it means your JSON array should already have fields mapped with respective field name NAME,DIRECTION, CHARGED and AFFORDED like this :
var dataSet = [
{ "NAME": "Name1", "DIRECTION": "Salida", "CHARGED": 15, "AFFORDED": 15 },
{ "NAME": "Name2", "DIRECTION": "Salida", "CHARGED": 4, "AFFORDED": 4 },
{ "NAME": "Name3", "DIRECTION": "Entrada", "CHARGED": 4, "AFFORDED": 4 },
{ "NAME": "Name4", "DIRECTION": "Salida", "CHARGED": 1, "AFFORDED": 0 },
{ "NAME": "Name5", "DIRECTION": "Entrada", "CHARGED": 15, "AFFORDED": 15 },
{ "NAME": "Name6", "DIRECTION": "Entrada", "CHARGED": 10, "AFFORDED": 10 },
{ "NAME": "Name7", "DIRECTION": "Entrada", "CHARGED": 15, "AFFORDED": 15 },
{ "NAME": "Name8", "DIRECTION": "Entrada", "CHARGED": 3, "AFFORDED": 3 },
{ "NAME": "Name9", "DIRECTION": "Entrada", "CHARGED": 15, "AFFORDED": 15}
];
Check this fiddle
In your case you want to have only data without field name since you are using embedded array, you should have something like :
var dataSet = [
["Name1", "Salida", "15", "15"],
["Name2", "Salida", "4", "4"],
["Name3", "Entrada", "4", "4"],
["Name4", "Salida", "1", "0"],
["Name5", "Entrada", "15", "15"],
["Name6", "Entrada", "10", "10"],
["Name7", "Entrada", "15", "15"],
["Name8", "Entrada", "3", "3"],
["Name9", "Entrada", "15", "15"]
];
You can change columns.data to column.title to set the data title directly for each array item index. Check this fiddle
As you have included field name in your data. The best is to modify your JSON input source to return something directly usable. If you can't doing it, you can modify the data you receive and reorganize it by removing the embedded field name and then initialize datatables with the new modified input.
annoyingmouse approach solved my problem.
My final call is:
var tableEntityList = $('#testable').DataTable({
"processing": true,
"scrollY":"500px",
"scrollCollapse": true,
"paging":false,
"serverSide":true,
"ajax":{
url:"./MyJson",
dataSrc: function(json) {
var properData = [];
$.each(json.data, function(k, v) {
var returnObject = {};
$.each(v, function(a, b) {
var elArr = b.split(":");
returnObject[elArr[0].trim()] = elArr[1].trim()
});
properData.push(returnObject)
});
return properData;
}
},
"columns": [
{ "data":'NAME' },
{ "data":'DIRECTION' },
{ "data":'CHARGED' },
{ "data":'AFFORDED' }
]
});
I'm creating a section of a site in Angular JS that displays some reporting data from the server. Since I'm displaying it in a table I need it in a format that can easily be displayed with ng-repeat.
I therefore need to translate JSON data from the server into a JavaScript object. I've got the target format of the data I want, an object that uses the names of the 'Donor Programs' as keys, and as their values an array of objects that each correspond to a month. Each of the objects has the name of the month, the amount of people who registered on the site, the amount of those people who donated, and the total amount donated.
I'm just having a really hard time iterating through the JSON and getting it to translate to that format. Can someone have a look? I've included both the server data I'm getting as well as how I'm trying to format it. Thanks.
Server Data:
$scope.serverData = {
"registration_by_month": [
{
"month": "November 2015",
"registration_program": "Donor Program 1",
"count": 3
},
{
"month": "November 2015",
"registration_program": "Donor Program 2",
"count": 4
},
{
"month": "December 2015",
"registration_program": "Donor Program 1",
"count": 5
},
{
"month": "December 2015",
"registration_program": "Donor Program 2",
"count": 6
}
],
"donors_by_month": [
{
"month": "November 2015",
"registration_program": "Donor Program 1",
"count": 2
},
{
"month": "November 2015",
"registration_program": "Donor Program 2",
"count": 1
},
{
"month": "December 2015",
"registration_program": "Donor Program 1",
"count": 2
},
{
"month": "December 2015",
"registration_program": "Donor Program 2",
"count": 1
}
],
"donated_amount_by_month": [
{
"month": "November 2015",
"registration_program": "Donor Program 1",
"amount": 100
},
{
"month": "November 2015",
"registration_program": "Donor Program 2",
"amount": 200
},
{
"month": "December 2015",
"registration_program": "Donor Program 1",
"amount": 50
},
{
"month": "December 2015",
"registration_program": "Donor Program 2",
"amount": 40
}
]
};
Target Data:
$scope.targetData = {
"Donor Program 1": [{month:"November 2015", registered:3, donors:2, donated_amount:100},{month:"December 2015", registered:4, donors:1, donated_amount:200}],
"Donor Program 2:": [{month:"November 2015", registered:5, donors:2, donated_amount:50},{month:"December 2015",registered:6, donors:1, donated_amount:40}]
};
Try like this
var temp = {};
data.registration_by_month.forEach(function (x) {
if (!temp[x.registration_program]) {
temp[x.registration_program] = [];
}
var dtmon = data.donors_by_month.find(function (y) {
return y.registration_program == x.registration_program;
});
var dnmon = data.donated_amount_by_month.find(function (y) {
return y.registration_program == x.registration_program;
});
temp[x.registration_program].push({
month: x.month,
registered: x.count,
donors: dtmon ? dtmon.count : 0,
donated_amount: dnmon ? dnmon.amount : 0
});
});
console.log(temp);
JSFIDDLE
EDIT
.find is not supported in IE and opera.
You can try .filter instead
Like this
var temp = {};
data.registration_by_month.forEach(function (x) {
if (!temp[x.registration_program]) {
temp[x.registration_program] = [];
}
var dtmon = data.donors_by_month.filter(function (y) {
return y.registration_program == x.registration_program;
});
var dnmon = data.donated_amount_by_month.filter(function (y) {
return y.registration_program == x.registration_program;
});
temp[x.registration_program].push({
month: x.month,
registered: x.count,
donors: dtmon.length > 0 ? dtmon[0].count : 0,
donated_amount: dnmon.length > 0 ? dnmon[0].amount : 0
});
});
JSFIDDLE
For Example If we have data for books, authors and date information. Can we build a crossfilter for how many books are present for author per month?
In pseudo sql terms, what you are trying to do is:
SELECT COUNT(book)
GROUP BY author, month
The way I approach this type of problem is to 'group' the fields together into a single dimension. So in your case I would concatenate the month and author information together, into a dimension.
Let this be our test data:
var cf = crossfilter([
{ date:"1 jan 2014", author: "Mr X", book: "Book 1" },
{ date:"2 jan 2014", author: "Mr X", book: "Book 2" },
{ date:"3 feb 2014", author: "Mr X", book: "Book 3" },
{ date:"1 mar 2014", author: "Mr X", book: "Book 4" },
{ date:"2 apr 2014", author: "Mr X", book: "Book 5" },
{ date:"3 apr 2014", author: "Mr X", book: "Book 6"},
{ date:"1 jan 2014", author: "Ms Y", book: "Book 7" },
{ date:"2 jan 2014", author: "Ms Y", book: "Book 8" },
{ date:"3 jan 2014", author: "Ms Y", book: "Book 9" },
{ date:"1 mar 2014", author: "Ms Y", book: "Book 10" },
{ date:"2 mar 2014", author: "Ms Y", book: "Book 11" },
{ date:"3 mar 2014", author: "Ms Y", book: "Book 12" },
{ date:"4 apr 2014", author: "Ms Y", book: "Book 13" }
]);
The dimension is defined as follows:
var dimensionMonthAuthor = cf.dimension(function (d) {
var thisDate = new Date(d.date);
return 'month='+thisDate.getMonth()+';author='+d.author;
});
And now we can just simply do a reduce count to calculate how many books there are per author, per month (i.e. per dimension unit):
var monthAuthorCount = dimensionMonthAuthor.group().reduceCount(function (d) { return d.book; }).all();
And the results are as follows:
{"key":"month=0;author=Mr X","value":2}
{"key":"month=0;author=Ms Y","value":3}
{"key":"month=1;author=Mr X","value":1}
{"key":"month=2;author=Mr X","value":1}
{"key":"month=2;author=Ms Y","value":3}
{"key":"month=3;author=Mr X","value":2}
{"key":"month=3;author=Ms Y","value":1}
I didn't find the accepted answer all that helpful.
I used the following instead.
I first made a keyed group (in your case month)
var authors = cf.dimension(function (d) {
return +d['month'];
})
Next, I used a map reduce method on the keyed dataset to compute the averages
The grouping helper function:
var monthsAvg = authors.group().reduce(reduceAddbooks, reduceRemovebooks, reduceInitialbooks).all();
The map-reduce functions:
function reduceAddbooks(p, v) {
p.author = v['author'];
p.books = +v['books'];
return p;
}
function reduceRemovebooks(p, v) {
p.author = v['author'];
p.books = +v['books'];
return p;
}
function reduceInitialbooks() {
return {
author:0,
books:0
};
}
I want to update an old answer with a new work around described in: https://github.com/dc-js/dc.js/pull/91
This performance hasn't been tested on large data-sets
var cf = crossfilter([
{ date:"1 jan 2014", author: "Mr X", book: "Book 1" },
{ date:"2 jan 2014", author: "Mr X", book: "Book 2" },
{ date:"3 feb 2014", author: "Mr X", book: "Book 3" },
{ date:"1 mar 2014", author: "Mr X", book: "Book 4" },
{ date:"2 apr 2014", author: "Mr X", book: "Book 5" },
{ date:"3 apr 2014", author: "Mr X", book: "Book 6"},
{ date:"1 jan 2014", author: "Ms Y", book: "Book 7" },
{ date:"2 jan 2014", author: "Ms Y", book: "Book 8" },
{ date:"3 jan 2014", author: "Ms Y", book: "Book 9" },
{ date:"1 mar 2014", author: "Ms Y", book: "Book 10" },
{ date:"2 mar 2014", author: "Ms Y", book: "Book 11" },
{ date:"3 mar 2014", author: "Ms Y", book: "Book 12" },
{ date:"4 apr 2014", author: "Ms Y", book: "Book 13" }
]);
var dimensionMonthAuthor = cf.dimension(function (d) {
var thisDate = new Date(d.date);
//stringify() and later, parse() to get keyed objects
return JSON.stringify ( { date: thisDate.getMonth() , author: d.author } ) ;
});
group = dimensionMonthAuthor.group();
//this forEach method could be very expensive on write.
group.all().forEach(function(d) {
//parse the json string created above
d.key = JSON.parse(d.key);
});
return group.all()
Results in:
[ { key: { date: 0, author: 'Mr X' },
value: 2 },
{ key: { date: 0, author: 'Ms Y' },
value: 3 },
{ key: { date: 1, author: 'Mr X' },
value: 1 },
{ key: { date: 2, author: 'Mr X' },
value: 1 },
{ key: { date: 2, author: 'Ms Y' },
value: 3 },
{ key: { date: 3, author: 'Mr X' },
value: 2 },
{ key: { date: 3, author: 'Ms Y' },
value: 1 } ]