Groupby array of object multiple times - arrays

considering the following data
let dataset =
[
{
"Category": "Auto",
"Parent": "Automotive",
"name": "Auto - Multi Purpose Vehicles",
"High": "10",
"Low": "15",
"Medium": "5"
},
{
"Category": "Auto",
"Parent": "Automotive",
"name": "Auto - Off road",
"High": "1",
"Low": "2",
"Medium": "3"
},
{
"Category": "Auto",
"Parent": "Ecology & Environment",
"name": "Vegetarian",
"High": "5",
"Low": "5",
"Medium": "10"
},
{
"Category": "Home",
"Parent": "Ecology & Environment",
"name": "Weather",
"High": "10",
"Low": "15",
"Medium": "5"
}]
I want to group data in the following way
[{
name: "Auto",
data: [{
name: "Automotive",
data: [{
name: "Auto - Multi Purpose Vehicles",
value: 30
High: 10,
Low: 15,
Medium: 5
},
{
name: "Auto - Off road",
value: 6
High: 1,
Low: 2,
Medium: 3
}]
}, {
name: 'Ecology & Environment',
data: [{
name: "Vegetarian",
value: 20
High: 5,
Low: 5,
Medium: 10
}]
}],
name: "Home",
data: [{
name: "Ecology & Environment",
data: [{
name: "Weather",
value: 30
High: 10,
Low: 15,
Medium: 5
}]
}]
}]
What I've tried so far never land me to the desired output.
here is where I'm stacked.
let cat = []
dataset.forEach((d) => {
const { Category, Parent, name, High, Medium, Low, value } = d;
let category = cat.find((item) => item.Category === Category);
let parent = cat.find((item) => item.data.Parent === Parent);
if (!category) {
cat.push({
Category,
data: []
})
} else if (!parent ) {
cat.forEach(i => {
i.data.push({
Parent,
High,
Medium,
Low
})
})
}
})
I've tried several ways with different results but I'm not able to figure out how to handle it
I'm not an expert in javascript. I'm trying to learn by doing but sometimes i get stack
Many thanks for any help
P.

In order to get the answer you want, follow this code.
step 1:
fire get the unique category from the dataset
step 2:
after getting a unique category, look for the particular category into a dataset, and when a category is found push it into the array
follow below code snippet
let dataset = [
{
Category: "Auto",
Parent: "Automotive",
name: "Auto - Multi Purpose Vehicles",
High: "10",
Low: "15",
Medium: "5",
},
{
Category: "Auto",
Parent: "Automotive",
name: "Auto - Off road",
High: "1",
Low: "2",
Medium: "3",
},
{
Category: "Auto",
Parent: "Ecology & Environment",
name: "Vegetarian",
High: "5",
Low: "5",
Medium: "10",
},
{
Category: "Home",
Parent: "Ecology & Environment",
name: "Weather",
High: "10",
Low: "15",
Medium: "5",
},
];
/* map function help us to get non unique
categoty like => [ 'Auto', 'Auto', 'Auto', 'Home' ]
`New Set()` object gave us unique array then
we create new array using spread oprator */
let uniqueCategory = [...new Set(dataset.map((data) => data.Category))];
let uniqueParent = [...new Set(dataset.map((data) => data.Parent))];
// create new array for storing final output
let cat = [];
// loop over unique category
uniqueCategory.forEach((Category) => {
// create new object for perticular category
let obj = {
name: Category,
data: [],
};
uniqueParent.forEach((parent) => {
let isDataEmpty = true;
let parentObj = {
name: parent,
data: [],
};
// loop over dataset
dataset.map((data) => {
/* if we fount category same as unique category we have
to push that data into particular category object */
if (data.Category === Category && data.Parent === parent) {
// delete category ket/value from object
isDataEmpty = false;
delete data.Category;
parentObj.data.push(data);
}
});
if (!isDataEmpty) obj.data.push(parentObj);
});
cat.push(obj);
});
console.log(cat);

Related

How can I group rows in react-data-table-component?

I am facing a problem when I need to group rows in a table using react-data-table-component.
My dataset:
const cars = [{
"brand": "audi",
"model": "a4",
"hp": "200",
},
{
"brand": "audi",
"model": "a5",
"hp": "300",
},
{
"brand": "audi",
"model": "rs6",
"hp": "500",
},
{
"brand": "tesla",
"model": "model 3",
"hp": "200",
},
{
"brand": "tesla",
"model": "model x",
"hp": "450",
}
];
The table should be structured like this:
How can I achieve this?
I am using hook-like style.
One can use cell property to render. So I create some index to track which brand has already been rendered and if a brand is already on the table it just returns an empty cell.
The code I am using:
const [brandIndex, setBrandIndex] = useState<(string | undefined)[]>([]);
const renderBrand = useCallback((row: CarDto) => {
const alreadyRendered = brandIndex.some(b => b === row.brand);
if (alreadyRendered) {
return null;
} else {
setBrandIndex(brandIndex.concat(row.brand));
return <span>{row.brand}</span>;
}
},[setBrandIndex, brandIndex])
//...
{
id: "brand",
name: "Brand",
selector: (row) => row.brand || "",
cell: renderBrand,
sortable: true,
resizable: true,
width: "200px",
},
Unfortunately this code is not working, all brands in my table are empty after rendering. The table renders a lot of times, so I assume that index contains all brands. The last rendering returns null in the first column.

Mongoose | Find objects inside of an array, that each object has another array of objects to satisfy condition

I have a collection Shops. Each object in Shops collection has an array of Item objects called items.
{
_id: ObjectId(...),
shopName: 'Ice cream Shop',
items: [
<Item>{
itemName: 'Chocolate IC',
availabilities: [
{
city: 'NY',
arrivals: [
{
price: 3.99,
quantityLeft: 0,
date: 'yesterday'
},
{
price: 3.99,
quantityLeft: 40,
date: 'today'
}
]
},
{
city: 'LA',
arrivals: []
}
]
},
<Item>{
itemName: 'Strawberry IC',
availabilities: [
{
city: 'NY',
arrivals: [
{
price: 3.99,
quantityLeft: 0,
date: 'yesterday'
},
]
}
]
},
],
},
... anotherShops
I want to get list of Item objects which has overall quantityLeft more than 0 from a specific shop.
I tried this code to get all items with the name start with "Straw" from a Shop with shopName equal to 'Ice cream Shop':
const items = await Shop.aggregate()
.match({
shopName: 'Ice cream Shop',
})
.project({
items: {
$filter: {
input: "$items",
as: "item",
cond: {
$regexMatch: {
input: "$$item.itemName",
regex: `.*Straw.*`,
},
},
},
},
});
And it works. But I don't know how to sum up all quantityLeft values inside availabilities array of each item, and return only that items that has sum more than 0.
availabilities array can be an empty array [].
The city parameter also needs to be in condition. For example, only Items that are in stock in NY
I need this to get the list of items from a certain shop, and only the items that are still in stock.
Pretty hard.
I came up with this solution. If you have a better solution, please post it.
const shop = await GCShop.aggregate([
{
$match: {
shopName: 'Ice Cream Shop',
},
},
{
$unwind: "$items",
},
{
$unwind: "$items.availabilities",
},
{
$unwind: "$items.availabilities.arrivals",
},
{
$group: {
_id: "$items.id",
items_name: { $first: "$items.name" },
arrivals: {
$push: {
arrival_id: "$items.availabilities.arrivals.arrival_id",
price: "$items.availabilities.arrivals.price",
qtty: "$items.availabilities.arrivals.qtty",
},
},
totalQtty: { $sum: "$items.availabilities.arrivals.qtty" },
},
},
{
$project: {
offer_id: "$_id",
_id: 0,
offer_name: 1,
totalQtty: 1,
arrivals: 1,
},
},
{
$match: {
totalQtty: {
$gt: 0,
},
},
},
]).limit(20);

Dynamically merge array objects

I want to combine two arrays (ranking and matches) that has common properties:
var ranking = [{
def: "0.58",
league: "Scottish Premiership",
name: "Celtic",
off: "3.33",
grank: "3",
tform: "96.33",
},
{
def: "2.52",
league: "Scottish Premiership",
name: "Dundee",
off: "1.28",
grank: "302",
tform: "27.51",
}]
var matches = [{
date: "2010-04-22",
league: "Scottish Premiership",
home: "0.0676",
away: "0.8",
draw: "0.1324",
goals1: "3",
goals2: "1",
tform1: "96.33",
tform2: "27.51",
team1: "Celtic",
team2: "Dundee",}]
Expected output looks like this:
[{
date: "2010-04-22",
league: "Scottish Premiership",
home: "0.0676",
away: "0.8",
draw: "0.1324",
goals1: "3",
goals2: "1",
tform1: "96.33",
tform2: "27.51",
def1: "0.58",
def2: "2.52",
off1: "3.33",
off2: "1.28",
grank1: "3",
grank2: "302",
team1: "Celtic",
team2: "Dundee",}]
To merge the arrays, I used Lodash _.merge function
var result = _.merge(ranking, matches);
The output it returned did merge some objects and omitted homogeneous objects.
Please I need some help and insight in achieving this task. I wouldn't mind any javascript (client-side) solution.
You need to merge by the given data and add the information of the two teams.
const
keys = ['def', 'off', 'grank'],
getRanking = (team, suffix) => Object
.fromEntries(keys.map(k => [k + suffix, team[k]])),
ranking = [{ def: "0.58", league: "Scottish Premiership", name: "Celtic", off: "3.33", grank: "3", tform: "96.33" }, { def: "2.52", league: "Scottish Premiership", name: "Dundee", off: "1.28", grank: "302", tform: "27.51" }],
matches = [{ date: "2010-04-22", league: "Scottish Premiership", home: "0.0676", away: "0.8", draw: "0.1324", goals1: "3", goals2: "1", tform1: "96.33", tform2: "27.51", team1: "Celtic", team2: "Dundee" }],
teams = Object.fromEntries(ranking.map(o => [o.name, o])),
result = matches.map(o => ({
...o,
...getRanking(teams[o.team1], 1),
...getRanking(teams[o.team2], 2)
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Combining Column charts and line charts with the same same data in the same container(Highcharts)

I want to build a combination chart with a column chart with multiple series and a line chart. Problem is that I am getting High charts data from nested JSON response. For that I initialized array and that array is giving in series in plotoptions highcharts as you can see in the below code.
My code is like this:
var crime_data=[];
for(var i=0;i<result.themes.length;i++){
var crime={};
var test2 = result.themes[i];
var test = test2[Object.keys(test2)];
crime.name = Object.keys(result.themes[i]);
crime.data = [];
for(var k=0;k<test.yearTheme.length;k++){
var test3=test.yearTheme[k];
var test5=test3.individualValueVariable;
for(var j=0;j<test5.length;j++){
crime.data.push(test5[j].count);
};
};
crime_data.push(crime);
};
var crimeChart = new Highcharts.Chart({
chart: {
renderTo: 'container1',
type:'column'
},
title: {
text: 'Crime'
},
xAxis: {
categories: month,
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Count'
}
},
credits: {
enabled: false
},
tooltip: {
shared: true,
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0,
depth: 25,
allowPointSelect: true,
cursor: 'pointer',
point: {
},
}
},
series: crime_data
});
This is Column chart I am getting when i write chart type column.
This is my Line Chart I am getting when i changed type column to spline in chart in highcharts.
And this is my JSON data(Highcharts data):
{
"boundaries": {
"boundary": [
{
"boundaryId": "55083021003",
"boundaryType": "USA_CITY",
"boundaryRef": "C1"
}
]
},
"themes": [
{
"AssaultCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [
{
"name": "2013 Assault Crime",
"description": "Assault Crime for 2013",
"count": 18901
},
{
"name": "2014 Assault Crime",
"description": "Assault Crime for 2014",
"count": 17707
}
]
}
},
{
"BurglaryCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [
{
"name": "2013 Burglary Crime",
"description": "Burglary Crime for 2013",
"count": 17743
},
{
"name": "2014 Burglary Crime",
"description": "Burglary Crime for 2014",
"count": 14242
}
]
}
}
]
}
I want to combine both of them in the same container with same data.The problem is in how to tell highcharts multiple series should be represented with line and with column type with same data.For this when i write series:[{ data: crime_data ,type: spline }] instead of series:crime_data In that case I am not getting Highcharts data. Can anyone Please help me how should i do this.Please suggest me.
Pass your data, like below format. add type of chart in each data series;
Here i replaced type value but with same data.
[{
type: 'line',
name: 'AssaultCrimeTheme',
data: [3, 2, 1, 3, 4]
}, {
type: 'line',
name: 'BurglaryCrimeTheme',
data: [2, 3, 5, 7, 6]
}, {
type: 'column',
name: 'AssaultCrimeTheme',
data: [3, 2, 1, 3, 4]
}, {
type: 'column',
name: 'BurglaryCrimeTheme',
data: [2, 3, 5, 7, 6]
},]
Here is fiddle for more details.
Here is a complete example using your data.
const json = {
"boundaries": {
"boundary": [{
"boundaryId": "55083021003",
"boundaryType": "USA_CITY",
"boundaryRef": "C1"
}]
},
"themes": [{
"AssaultCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [{
"name": "2013 Assault Crime",
"description": "Assault Crime for 2013",
"count": 18901
}, {
"name": "2014 Assault Crime",
"description": "Assault Crime for 2014",
"count": 17707
}]
}
}, {
"BurglaryCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [{
"name": "2013 Burglary Crime",
"description": "Burglary Crime for 2013",
"count": 17743
}, {
"name": "2014 Burglary Crime",
"description": "Burglary Crime for 2014",
"count": 14242
}]
}
}]
}
// Create categories object in order filter duplicates
const cats = {}
const series = json.themes.map((o) => {
const key = Object.keys(o)[0]
return {
name: key,
data: o[key].individualValueVariable.map((o) => {
cats[o.name] = 1
return { category: o.name, y: o.count }
})
}
})
// Convert categories object to array
const categories = Object.keys(cats)
// Chart options
const options = {
chart: {type: 'column'},
xAxis: {categories: categories},
series: series
}
// Create chart
const chart = Highcharts.chart('container', options)
console.log(series, categories)
Live example: https://jsfiddle.net/Lo323gq3/
Output below:

How can I change the attribute in dataset of Fusionchart?

Hi I am implementing a chart in my Angularjs Application, You can see this plunker http://jsfiddle.net/fusioncharts/73xgmacm/ The thing which I want to achieve is to change the value attribute to profit. How can I do this ? I want to display profit not values.
Regards
After 2 days I finally find out the answer. The thing is You cannot change the Fusionchart attribute value but you can change the attribute of your API once you fetched. I used a loop after I fetched the API and replace the 'profit' attribute with value in this way I made the chart. Yes The thing which i had been ignoring was the use of 'variable' instead of scope. If you see this example you would understand Example Here. I am sharing my code May be it helps someone else too.
Give below is my json array which i called tps.json
[
{
"index": "1",
"variantoption": "fan-green",
"company": "sk fans",
"quantity": "650",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "2",
"variantoption": "fan-white",
"company": "al ahmed fans",
"quantity": "450",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "3",
"variantoption": "fan-purple",
"company": "asia fans",
"quantity": "350",
"profit": "78296",
"loss": "8457",
"year": "2016"
},
{
"index": "4",
"variantoption": "fan-yellow",
"company": "falcon fans",
"quantity": "250",
"profit": "78296",
"loss": "8457",
"year": "2016"
}
]
and here is my controller
$http.get('js/tps.json').success(function (data) {
var chartdata = data;
var arrLength = chartdata.length;
console.log(arrLength);
for (var i = 0; i < arrLength; i++) {
if (chartdata[i]['profit'] && chartdata[i]['index']) {
chartdata[i].value = chartdata[i].profit;
delete chartdata[i].profit;
chartdata[i].label = chartdata[i].index;
delete chartdata[i].index;
console.log(chartdata);
}
}
console.log(chartdata);
FusionCharts.ready(function () {
var tps = new FusionCharts({
type: 'column2d',
renderAt: 'chart-container',
width: '500',
height: '300',
dataFormat: 'json',
dataSource: {
"chart": {
"caption": "Monthly",
"xaxisname": "Month",
"yaxisname": "Revenue",
"numberprefix": "$",
"showvalues": "1",
"animation": "1"
},
"data" : chartdata
}
});
tps.render();
});
}
);
}
-Stay foolish stay hungry

Resources