Javascript groupby and sum key value - javascript

I have the following array of dicts
var response = [{
"ShoppingCart": "cart1",
"Class": "Gen",
"Type": "300",
"SubClass": "Mens",
"Points": 0.9
},
{
"ShoppingCart": "cart2",
"Class": "Lux",
"Type": "3002C",
"SubClass": "Mens",
"Points": 0.75
},
{
"ShoppingCart": "cart3",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
},
{
"ShoppingCart": "cart4",
"Class": "Lux",
"Type": "300",
"SubClass": "Cabin",
"Points": 1
},
{
"ShoppingCart": "cart5",
"Class": "Comfort",
"Type": "380",
"SubClass": "Ladies",
"Points": 1
},
{
"ShoppingCart": "cart6",
"Class": "Gen",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.9
},
{
"ShoppingCart": "cart7",
"Class": "Gen",
"Type": "300",
"SubClass": "Cabin",
"Points": 0.7
},
{
"ShoppingCart": "cart8",
"Class": "Gen",
"Type": "380PC",
"SubClass": "Ladies",
"Points": 0.7
},
{
"ShoppingCart": "cart9",
"Class": "Lux",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.5
},
{
"ShoppingCart": "cart10",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
}
]
I am using reduce function and When i do a groupby and sum the Points , the Class is repeated and not unique , How can i perform a groupby and sum the unique values .
I know lodash's groupby function solves, how can i do it with the reduce function itself ?
The last Class comfort is not coming in the output , why is that ?
the code so far
result = [];
response.reduce(function(res, value) {
if (!res[value.Type]) {
res[value.Type] = { Type: value.Type, Class: value.Class, Points: 0 };
result.push(res[value.Type])
}
res[value.Type].Points += parseFloat(value.Points);
return res;
}, {});
console.log(result);
result:
[
{ Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
{ Type: '3002C', Class: 'Lux', Points: 0.75 },
{ Type: '380', Class: 'Lux', Points: 3.4 },
{ Type: '380PC', Class: 'Gen', Points: 0.7 }
]
expected result:
[
{ Type: '300', Class: 'Gen', Points: 2.5999999999999996 },
{ Type: '3002C', Class: 'Lux', Points: 0.75 },
{ Type: '380', Class: 'Lux', Points: 3.4 },
{ Type: '380PC', Class: 'Gen', Points: 0.7 },
{ Type: '380', Class: 'Comfort', Points: 1 }
]
What am i missing in this reduce function ?
Modified Code as per epascarello's suggestions
response.reduce(function(res, value) {
const key = value.Type + "-" + value.Class;
if (!res[key]) {
res[key] = { Type: value.Type, Class: value.Class, Points: 0 };
result.push(res[key])
}
res[key].Points += parseFloat(value.Points);
return res;
}, {});
console.log(result);

So make your key based off the two properties, not just one
const key = value.Type + "-" + value.Class;
if (!res[key]) {

I think this is more what you're looking for.
Basically, for each item in response it will try to find an item in the results array that has the same Type and Class as the provided item. If it finds one it will increment that item's Points by the provided Points, if not it will append a new item onto the results array.
.reduce is a very useful function, but how you had it before was not utilizing its capabilities.
var response = [{
"ShoppingCart": "cart1",
"Class": "Gen",
"Type": "300",
"SubClass": "Mens",
"Points": 0.9
},
{
"ShoppingCart": "cart2",
"Class": "Lux",
"Type": "3002C",
"SubClass": "Mens",
"Points": 0.75
},
{
"ShoppingCart": "cart3",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
},
{
"ShoppingCart": "cart4",
"Class": "Lux",
"Type": "300",
"SubClass": "Cabin",
"Points": 1
},
{
"ShoppingCart": "cart5",
"Class": "Comfort",
"Type": "380",
"SubClass": "Ladies",
"Points": 1
},
{
"ShoppingCart": "cart6",
"Class": "Gen",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.9
},
{
"ShoppingCart": "cart7",
"Class": "Gen",
"Type": "300",
"SubClass": "Cabin",
"Points": 0.7
},
{
"ShoppingCart": "cart8",
"Class": "Gen",
"Type": "380PC",
"SubClass": "Ladies",
"Points": 0.7
},
{
"ShoppingCart": "cart9",
"Class": "Lux",
"Type": "380",
"SubClass": "Cabin",
"Points": 0.5
},
{
"ShoppingCart": "cart10",
"Class": "Lux",
"Type": "380",
"SubClass": "Ladies",
"Points": 0.5
}
];
var grouped = response.reduce((res, value) => {
const ext = res.find(({
Type,
Class
}) => {
return Type === value.Type && Class === value.Class;
});
if (ext) {
ext.Points += value.Points;
} else {
res.push({
Type: value.Type,
Class: value.Class,
Points: value.Points
});
}
return res;
}, []);
console.log(grouped);

Related

I need to sort an array in javascript

I am getting json data like this
[
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
{
"emission": [
{
"id": "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0",
"size": "",
},
{
"id": "f670609a-d200-4c03-a8a7-34e2b244a4c7",
"size": "Small",
}
],
"id": "95a9c2eb-7dac-45d6-9a6a-2718859d91f3",
},
{
"emission": [
{
"id": "77f5b953-772a-4e02-834f-6d7eb4236223",
"size": "Medium",
},
{
"id": "04e909bc-0087-479d-9f4d-8f4ad03f8dd0",
"size": "Large",
},
{
"id": "4a628027-3ec8-450c-943e-7dce96f0bbb4",
"size": "Small",
},
{
"id": "7c5c638b-bab6-4a10-ba3e-ebdc8939021d",
"size": "Large",
}
],
"id": "bc38b226-78cd-4928-80a0-589a9da2cd40",
},
{
"emission": [
{
"id": "e6011db7-0662-4b52-9d26-e6be07226826",
"size": "Large",
},
{
"id": "ad678447-3e18-4537-baa1-b762dc03f6cd",
"size": "Medium",
}
],
"id": "e1c59ebd-b567-462f-ac00-068ff7938055",
},
{
"emission": [
{
"id": "3525d215-e9eb-4417-8b35-902936181d29",
"size": "Medium",
},
{
"id": "4c023985-a3c0-4783-a9c3-d51a21bf63d9",
"size": "Large",
},
{
"id": "7ef8d908-8a29-4d40-bdfe-121895d01ebc",
"size": "Medium",
}
],
"id": "d9e88ddc-1b7e-4a68-b087-46d365f266a3",
}
]
I need to reorder entire data based on emission array's size like large, medium and small, so that first array must be no of count of Large, then medium and small, it needs to be sorted
Note: some data can also be without size those data can be omitted, but still needs to be present in final sorted array
Output:
[
{
"emission": [
{
"id": "77f5b953-772a-4e02-834f-6d7eb4236223",
"size": "Medium",
},
{
"id": "04e909bc-0087-479d-9f4d-8f4ad03f8dd0",
"size": "Large",
},
{
"id": "4a628027-3ec8-450c-943e-7dce96f0bbb4",
"size": "Small",
},
{
"id": "7c5c638b-bab6-4a10-ba3e-ebdc8939021d",
"size": "Large",
}
],
"id": "bc38b226-78cd-4928-80a0-589a9da2cd40",
},
{
"emission": [
{
"id": "3525d215-e9eb-4417-8b35-902936181d29",
"size": "Medium",
},
{
"id": "4c023985-a3c0-4783-a9c3-d51a21bf63d9",
"size": "Large",
},
{
"id": "7ef8d908-8a29-4d40-bdfe-121895d01ebc",
"size": "Medium",
}
],
"id": "d9e88ddc-1b7e-4a68-b087-46d365f266a3",
},
{
"emission": [
{
"id": "e6011db7-0662-4b52-9d26-e6be07226826",
"size": "Large",
},
{
"id": "ad678447-3e18-4537-baa1-b762dc03f6cd",
"size": "Medium",
}
],
"id": "e1c59ebd-b567-462f-ac00-068ff7938055",
},
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
{
"emission": [
{
"id": "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0",
"size": "",
},
{
"id": "f670609a-d200-4c03-a8a7-34e2b244a4c7",
"size": "Small",
}
],
"id": "95a9c2eb-7dac-45d6-9a6a-2718859d91f3",
}
]
You could count wanted type and sort descending.
const
count = ({ emission }, type) =>
emission.reduce((r, { size }) => r + (type === size), 0),
data = [{ emission: [{ id: "fffda276-c7ed-4931-8211-48b3ae304b6f", size: "Medium" }], id: "db9dd205-5986-432f-9aaf-1079d6fdd28c" }, { emission: [{ id: "5ae8991c-bbcd-4a97-a5ad-b1aac6d765c0", size: "" }, { id: "f670609a-d200-4c03-a8a7-34e2b244a4c7", size: "Small" }], id: "95a9c2eb-7dac-45d6-9a6a-2718859d91f3" }, { emission: [{ id: "77f5b953-772a-4e02-834f-6d7eb4236223", size: "Medium" }, { id: "04e909bc-0087-479d-9f4d-8f4ad03f8dd0", size: "Large" }, { id: "4a628027-3ec8-450c-943e-7dce96f0bbb4", size: "Small" }, { id: "7c5c638b-bab6-4a10-ba3e-ebdc8939021d", size: "Large" }], id: "bc38b226-78cd-4928-80a0-589a9da2cd40" }, { emission: [{ id: "e6011db7-0662-4b52-9d26-e6be07226826", size: "Large" }, { id: "ad678447-3e18-4537-baa1-b762dc03f6cd", size: "Medium" }], id: "e1c59ebd-b567-462f-ac00-068ff7938055" }, { emission: [{ id: "3525d215-e9eb-4417-8b35-902936181d29", size: "Medium" }, { id: "4c023985-a3c0-4783-a9c3-d51a21bf63d9", size: "Large" }, { id: "7ef8d908-8a29-4d40-bdfe-121895d01ebc", size: "Medium" }], id: "d9e88ddc-1b7e-4a68-b087-46d365f266a3" }];
data.sort((a, b) =>
count(b, 'Large') - count(a, 'Large') ||
count(b, 'Medium') - count(a, 'Medium') ||
count(b, 'Small') - count(a, 'Small')
);
console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I couldn't fully understand what you meant, but I assume a sorting by Large, Medium and Small might help you
let data = [
{
"emission": [
{
"id": "fffda276-c7ed-4931-8211-48b3ae304b6f",
"size": "Medium",
}
],
"id": "db9dd205-5986-432f-9aaf-1079d6fdd28c",
},
// ... other data objects
];
let sortedData = data.sort((a, b) => {
let aCount = countSizes(a.emission, 'Large');
let bCount = countSizes(b.emission, 'Large');
if (aCount !== bCount) {
return bCount - aCount;
}
aCount = countSizes(a.emission, 'Medium');
bCount = countSizes(b.emission, 'Medium');
if (aCount !== bCount) {
return bCount - aCount;
}
aCount = countSizes(a.emission, 'Small');
bCount = countSizes(b.emission, 'Small');
return bCount - aCount;
});
function countSizes(emission, size) {
return emission.filter(e => e.size === size).length;
}
console.log(sortedData);
Explanation:
In the code, the countSizes function is used to count the number of occurrences of a specific size in the emission array. The sort method is used to sort the data array based on the number of occurrences of Large, Medium, and Small sizes, in that order. The resulting sortedData array will have the data objects ordered based on the number of occurrences of the sizes in the emission array.

Is it possible to print the label of the object instead the id in material ui DataGrid

So I have two tables in my database. I want a DataGrid UI to print all my columns except the categoryId I want to print a label instead (like in selection valueOptions) :
const columns: GridColDef = [
{
"field": "title",
"headerName": "Titel",
"width": 350,
"editable": true
},
{
"field": "categoryId",
"headerName": "Kategorie",
"width": 250,
"editable": true,
"type": "singleSelect",
"valueOptions": [
{
"value": "miv560972ynqzk9",
"label": "stuff 1"
},
{
"value": "1t7n08l9tfdwotn",
"label": "stuff 2"
},
]
}
]
const rows: GridRowsProp = [
{
"categoryId": "miv560972ynqzk9",
"title": "Lineare Algebra Hausaufga",
},
{
"categoryId": "1t7n08l9tfdwotn",
"title": "Test",
},
]
So I want something like this:
const rows: GridRowsProp = [
{
"categoryId": { value:"miv560972ynqzk9", label: "stuff1"},
"title": "Lineare Algebra Hausaufga",
},
{
"categoryId": { value: "1t7n08l9tfdwotn", label: "stuff2" },
"title": "Test",
},
]

Select items that have at least one digit from object in javascript

{
"images": [
{
"key": "ASDV1-01.jpg",
"image_location": "image1.jpg",
"data": {
"documentid": "CE44DBAC-59B2-4178-8392-0141FB2F58DF",
"scandate": "Feb 1 2018 12:05PM",
"F08": "1",
"F09": "",
"F10": "101076",
"F11": ""
},
"crops": {
"F08": {
"rectangle": {
"left": 690,
"top": 2111,
"width": 597,
"height": 121
}
},
"F09": {},
"F10": {
"rectangle": {
"left": 653,
"top": 821,
"width": 653,
"height": 243
}
},
"F11": {}
}
},
{
"key": "ASDV1-01.jpg",
"image_location": "image.png",
"crops": {
"F05": {
"rectangle": {
"left": 0,
"top": 808,
"width": 624,
"height": 243
}
}
},
"metadata": [
{
"name": "colors",
"data": {
"dimensions": {
"width": 2000,
"height": 2600
},
"coordinates": {
"width": {
"x": {
"lat": 4,
"long": [12, 345]
},
"y": {
"lat": {
"x" : [12,345],
"y": "234"
},
"long": 123
}
}
}
}
}
]
},
{
"key": "ASDV1-02.jpg",
"image_location": "image.png"
}
]
}
My main goal is to loop through this and return a new object containing items that have at least one digit so in the end i will have something similar to this example. The new object should be a new JSON file:
{
"key": "ASDV1-01.jpg",
"data": {
"documentid": "CE44DBAC-59B2-4178-8392-0141FB2F58DF",
"scandate": "Feb 1 2018 12:05PM",
"F08": "1",
"F10": "101076",
}
}
Of course, this should be applied for the whole object. Tried to do this with regex syntax but with no use. Thank you in advance
By digit you mean like 0 or a? (then it would be a character) you can loop trough the whole Json and check for each key if the corresponding value is len() >= 1 if it is, then add it to a new Object. You can also use a filter like in this example (example for getting all odd numbers):
const odd = x => x % 2 === 1;
[1, 2, 3].filter(x => x % 2 === 1);
Have a look here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
loop through whole array of images and test() key if it contains any digit with /\d/ regex
let data = [
{ "key": "no-digit.jpg" },
{ "key": "has2-digits7.jpg" },
{ "key": "again-no-digit.jpg" }
];
data = data.filter(item => /\d/.test(item.key));
console.log(data);

i use dTree.js created a family tree chart, but how can i create only one mother marry father

this picture is i use dTree.js created a family tree chart; there is two mother; but this is not I want;
this is my code
[
{
"name": "granddad",
"class": "man",
"textClass": "emphasis",
"marriages": [
{
"spouse": {
"name": "grandmother",
"class": "woman"
},
"children": [
{
"name": "aunt",
"class": "woman"
},
{
"name": "uncle",
"class": "man"
},
{
"name": "father",
"class": "man",
"marriages": [
{
"spouse": {
"name": "mother",
"class": "woman",
"id": 3
},
"children": [
{
"name": "sister",
"class": "woman"
},
{
"name": "me",
"class": "man"
},
{
"name": "brother",
"class": "man",
"hidden": true
}
]
}
]
}
]
}
]
},
{
"name": "grandfather",
"class": "man",
"textClass": "emphasis",
"marriages": [
{
"spouse": {
"name": "grandmother",
"class": "woman"
},
"children": [
{
"name": "mother",
"class": "woman",
"id": "3"
},
{
"name": "aunt",
"class": "woman"
}
]
}
]
}
]
<script>
var data_json = '/admin/test/json';
treeJson = d3.json(data_json, function (error, treeData) {
dTree.init(treeData, {
target: "#graph",
debug: true,
height: 800,
width: 1200,
callbacks: {
nodeClick: function (name, extra) {
console.log(name);
}
}
});
});
i want to create a chart like this : there is only one mother marry to father;
https://i.stack.imgur.com/db8I3.jpg
how can I do it?

Fuzzy search deep array only on certain properties

I have a JSON dataset which could be very large when it returns, with the following structure for each object:
{
"ctr": 57,
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}
Now I want to search all objects in the array and return only objects which include a string of some sort, but I only want to search certain properties.
I basically have another array which contains the keys I want to search, e.g.
const iteratees = ['ctr', 'property.value', 'status.stage']
I have lodash available within the project, but I have no idea where to start.
Any ideas?
You could use filter(), some() and reduce() to do this.
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if(a) return a[b];
}, o);
if(res) {
if((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
var arr = [{
"ctr": 'lorem',
"averageECPC": 23,
"cost": 2732.54,
"margin": 66,
"profit": 2495.9,
"property": {
"value": "Izzby",
"uri": "/Terrago/2"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 2573.13,
"compare": 0
},
"children": [{
"ctr": 79,
"averageECPC": 54,
"cost": 3554.78,
"margin": 88,
"profit": 3145.81,
"property": {
"value": "Comvex",
"uri": "/Octocore/4"
},
"status": {
"content": "<p>Some Content</p>",
"stage": 1
},
"alerts": {
"status": 2
},
"revenue": {
"value": 1247.92,
"compare": 0
}
}]
}, {
name: 'lorem',
ctr: 12,
property: {
value: 1
},
status: {
stage: 1
}
}, {
name: 'ipsum'
}]
const iteratees = ['ctr', 'property.value', 'status.stage'];
var searchFor = 'lo';
var result = arr.filter(function(o) {
return iteratees.some(function(e) {
var res = e.split('.').reduce(function(a, b) {
if (a) return a[b];
}, o);
if (res) {
if ((res).toString().indexOf(searchFor) != -1) return true;
}
})
})
console.log(result)

Categories

Resources