Lodash to subgroup items in Array of Objects - javascript

I have an Array of objects with band property. i would like to group them according to band
I have tried _groupBy and failed to get expected result
var data=[
{
"tOffice": 123,
"cType": 5000,
"band": -4877,
"minCh": 12,
"maxCh": 20
},
{
"tOffice": 123,
"cType": 5000,
"band": -4877,
"minCh": 1,
"maxCh": 2
},
{
"tOffice": 123,
"cType": 5000,
"band": -4877,
"minCh": 11,
"maxCh": 12
},
{
"tOffice": 123,
"cType": 6000,
"band": -5877,
"minCh": 11,
"maxCh": 12
},
{
"tOffice": 456,
"cType": 5000,
"band": -4544,
"minCh": 12,
"maxCh": 20
},
{
"tOffice": 456,
"cType": 5000,
"band": -4544,
"minCh": 10,
"maxCh": 11
},
{
"tOffice": 456,
"cType": 6000,
"band": -5211,
"minCh": 12,
"maxCh": 20
},
{
"tOffice": 456,
"cType": 6000,
"band": -5211,
"minCh": 12,
"maxCh": 20
},
{
"tOffice": 456,
"cType": 6000,
"band": -5211,
"minCh": 12,
"maxCh": 20
}
];
Expected Output:
var expectedResult = [{
tOffice: 123,
bandType: [{
band: '123-5000',
minMaxCharge: [{
minCh: 12,
maxCh: 20
}, {
minCh: 1,
maxCh: 2
}, {
minCh: 11,
maxCh: 12
}]
},
{
band: '123-6000',
minMaxCharge: [{
minCh: 11,
maxCh: 12
}]
}
]
}, {
tOffice: 456,
bandType: [{
band: '456-5000',
minMaxCharge: [{
minCh: 12,
maxCh: 20
}, {
minCh: 10,
maxCh: 11
}]
},
{
band: '456-6000',
minMaxCharge: [{
minCh: 12,
maxCh: 20
}, {
minCh: 12,
maxCh: 20
}]
}
]
}]
The expected result should contain a tOffice with max 2 combinations(5000 & 6000), band is a combination of tOffice+cType.
_.chain(data).groupBy("band").map(function(v, i) {
return {
}
})
I have tried some ES6 way and found that lodash methods will be a good choice, but i am not aware about that

This is a vanila js solution. You could do something like this using reduce and Object.values
var data=[{"tOffice":123,"cType":5000,"band":-4877,"minCh":12,"maxCh":20},{"tOffice":123,"cType":5000,"band":-4877,"minCh":1,"maxCh":2},{"tOffice":123,"cType":5000,"band":-4877,"minCh":11,"maxCh":12},{"tOffice":123,"cType":6000,"band":-5877,"minCh":11,"maxCh":12},{"tOffice":456,"cType":5000,"band":-4544,"minCh":12,"maxCh":20},{"tOffice":456,"cType":5000,"band":-4544,"minCh":10,"maxCh":11},{"tOffice":456,"cType":6000,"band":-5211,"minCh":12,"maxCh":20},{"tOffice":456,"cType":6000,"band":-5211,"minCh":12,"maxCh":20},{"tOffice":456,"cType":6000,"band":-5211,"minCh":12,"maxCh":20}];
const merged = data.reduce((r,{tOffice, cType, minCh, maxCh})=>{
const office = r[tOffice] = r[tOffice] || {tOffice, bandType:{}};
const band = `${tOffice}-${cType}`
const nested = office.bandType[band]
= office.bandType[band] || {band, minMaxCharge:[]};
nested.minMaxCharge.push({minCh, maxCh})
return r
},{})
const final = Object.values(merged);
final.forEach(a => a.bandType = Object.values(a.bandType))
console.log(final)

Related

How do I properly sort this array?

I've created a couple arrays. arrLocations holds a series of 2-digit country names, arrResults counts how many times each occurs and holds the country name with it's count as see here:
[
FR: 40, US: 1511, AU: 82,
CN: 151, IE: 170, SG: 108,
GB: 66, KR: 52, JP: 137,
IN: 45, BR: 68, SE: 39,
ZA: 19, NL: 19, BH: 19,
LU: 3, CA: 41, DE: 79,
ID: 1, HK: 1
]
My intention is to sort this array by ascending occurrence, I want this:
[
ID: 1, HK: 1, LU: 3,
BH: 19, NL: 19, ZA: 19,
....and so on........
]
However, no matter what way I implement sort, it does absolutely nothing. I even did a test sort on a dumby array and was able to sort it fine, but this array I cannot sort.
Here is what I have so far:
var geoip = require('geoip-lite')
const fs = require('fs')
const { Console } = require('console')
let data = fs.readFileSync('./ip_new.txt')
let iplocation = ""
let arrLocations = []
let arrResults = []
let arrIP = data.toString().split("\r\n")
for(let item of arrIP){
iplocation = geoip.lookup(item)
arrLocations.push(iplocation.country)
}
for(let item of arrLocations){
if (item in arrResults){
arrResults[item]++
}
else{
arrResults[item]=1
}
}
arrResults.sort()
console.log(arrResults)
OK, so first of all I'm assuming this
[
FR: 40, US: 1511, AU: 82,
CN: 151, IE: 170, SG: 108,
GB: 66, KR: 52, JP: 137,
IN: 45, BR: 68, SE: 39,
ZA: 19, NL: 19, BH: 19,
LU: 3, CA: 41, DE: 79,
ID: 1, HK: 1
]
Is actually this
[
{ FR: 40 }, { US: 1511 }, { AU: 82 },
{ CN: 151 }, { IE: 170 }, { SG: 108 },
{ GB: 66 }, { KR: 52 }, { JP: 137 },
{ IN: 45 }, { BR: 68 }, { SE: 39 },
{ ZA: 19 }, { NL: 19 }, { BH: 19 },
{ LU: 3 }, { CA: 41 }, { DE: 79 },
{ ID: 1 }, { HK: 1 }
]
If this is true, then sort method will not work on it's own. The following will do though:
const arrResults = [
{ FR: 40 }, { US: 1511 }, { AU: 82 },
{ CN: 151 }, { IE: 170 }, { SG: 108 },
{ GB: 66 }, { KR: 52 }, { JP: 137 },
{ IN: 45 }, { BR: 68 }, { SE: 39 },
{ ZA: 19 }, { NL: 19 }, { BH: 19 },
{ LU: 3 }, { CA: 41 }, { DE: 79 },
{ ID: 1 }, { HK: 1 }
];
arrResults.sort((a, b) => {
const countryCodeA = Object.keys(a)[0];
const countryCodeB = Object.keys(b)[0];
return a[countryCodeA] - b[countryCodeB];
});

How to select random object from JSON file in discord.js

I've done some searching around and I found some posts on here but my code doesn't want to work.
Basically I'm making a discord bot and I want to select an object from a JSON file at random.
This is my command:
const UserData = require('../data/users.js');
const monster = require('../data/monsters.json');
module.exports = {
name: 'battle',
aliases: ['fight'],
cooldown: 0,
description: 'User fights against a monster alone or in group',
execute(client, message, args) {
let enemy = monster[Math.floor(Math.random() * monster.length)]
UserData.findOne({
userID: message.author.id
}, (error, userdata) => {
if (error) console.log(error);
if (!userdata) {
return message.reply(`you don't have an account!`);
} else {
console.log(enemy);
return message.channel.send(`${enemy} spawned!`);
}
})
}
}
And this is my JSON file:
"1" : {
"name": "Blue Slime",
"hp": 20,
"atk": 12,
"def": 10,
"spatk": 3,
"spdef": 12,
"spd": 100,
"gold": 10,
"xp": 50,
"lvl": 1
},
"2": {
"name": "Red slime",
"hp": 20,
"atk": 12,
"def": 10,
"spatk": 3,
"spdef": 12,
"spd": 100,
"gold": 10,
"xp": 50,
"lvl": 1
},
"3": {
"name": "Green slime",
"hp": 20,
"atk": 12,
"def": 10,
"spatk": 3,
"spdef": 12,
"spd": 100,
"gold": 10,
"xp": 50,
"lvl": 1
}
}
If I want put the objects in the command manually and then randomly select them it works and if instead of "monster.length" I put a number then it also works but I still get undefined if it should be 3.
This way I also always get undefined in console log from monster.length.
What am I doing wrong?
Your monsters.json file contains an object and objects don't have lengths. You can however convert it to an array, using Object.values() that returns an array of the given object's own enumerable property values.
Check out the snippet below:
let monsters = {
1: {
name: 'Blue Slime',
hp: 20,
atk: 12,
def: 10,
spatk: 3,
spdef: 12,
spd: 100,
gold: 10,
xp: 50,
lvl: 1,
},
2: {
name: 'Red slime',
hp: 20,
atk: 12,
def: 10,
spatk: 3,
spdef: 12,
spd: 100,
gold: 10,
xp: 50,
lvl: 1,
},
3: {
name: 'Green slime',
hp: 20,
atk: 12,
def: 10,
spatk: 3,
spdef: 12,
spd: 100,
gold: 10,
xp: 50,
lvl: 1,
},
};
function randomObject(obj) {
let arr = Object.values(obj);
return arr[Math.floor(Math.random() * arr.length)];
}
let enemy = randomObject(monsters);
console.log(enemy);

javascript JSON : Sum two or more json having only numeric values with same keys

I am new to Nodejs and typescript.I have below two jsons :
json1 =
{
"201809": 2,
"metric": "headcount",
"quarter1": 60,
"careerLevelsGroups": [{
"201809": 2,
"quarter1": 60,
"careerLevels": [{
"201809": 2,
"careerId": "careerId1",
"quarter1": 60,
},
{
"201809": 2,
"careerId": "careerId2",
"quarter1": 50,
}
]
}]
}
json2 =
{
"201809": 3,
"metric": "headcount",
"quarter1": 100,
"careerLevelsGroups": [{
"201809": 7,
"quarter1": 40,
"careerLevels": [{
"201809": 9,
"careerId": "careerId1",
"quarter1": 30,
},
{
"201809": 8,
"careerId": "careerId2",
"quarter1": 30,
}
]
}]
}
I want to sum all the numeric values associated with the same keys and produce a single json having the summed values of json1 and json2.
result =
{
"201809": 5,
"metric": "headcount",
"quarter1": 160,
"careerLevelsGroups": [{
"201809": 9,
"quarter1": 100,
"careerLevels": [{
"201809": 11,
"careerId": "careerId1",
"quarter1": 90,
},
{
"201809": 10,
"careerId": "careerId2",
"quarter1": 80,
}
]
}]
}
I am trying to use a loop but i have too many such elements which i need to sum so can you please suggest a more optimised method to be used in Node.js
I put together a combine() function which uses recursion for processing members of the JSON object. If it detects a "number" it combines it. If it detects an "object" it applies recursion to search for more "number" or "object" inside it. For any other type (e.g. "string") it just leaves the values as is.
function combine(acc, curr) {
for (var key in acc) {
switch (typeof(acc[key])) {
case "number":
acc[key] += curr[key];
break;
case "object":
combine(acc[key], curr[key]);
break;
}
}
}
var json1 =
{
"201809": 2,
"metric": "headcount",
"quarter1": 60,
"careerLevelsGroups": [{
"201809": 2,
"quarter1": 60,
"careerLevels": [{
"201809": 2,
"careerId": "careerId1",
"quarter1": 60,
},
{
"201809": 2,
"careerId": "careerId2",
"quarter1": 50,
}
]
}]
};
var json2 =
{
"201809": 3,
"metric": "headcount",
"quarter1": 100,
"careerLevelsGroups": [{
"201809": 7,
"quarter1": 40,
"careerLevels": [{
"201809": 9,
"careerId": "careerId1",
"quarter1": 30,
},
{
"201809": 8,
"careerId": "careerId2",
"quarter1": 30,
}
]
}]
};
var res = json1;
combine(res, json2);
console.log(JSON.stringify(json1, undefined, 2));
Running the script produces the desired output. It should be a straightforward execise, to iterate through a series of these JSON objects to generate the result required.

show only part of the text on h-axis

I am working on angularjs google charts.
Please find the demo here
I want to show different value to be displayed on h-axis and tooltip.
In the below code, i want to show only the month name on the h-axis and both month and year on tooltip.
Any advices?
js code:
angular.module('myApp', ['googlechart'])
.controller('myController', function($scope) {
var chart1 = {};
chart1.type = "ColumnChart";
chart1.displayed = false;
chart1.data = {
"cols": [{
id: "month",
label: "Month",
type: "string"
}, {
id: "laptop-id",
label: "Laptop",
type: "number"
} ],
"rows": [{
c: [{
v: "January" + " 2017"
}, {
v: 19,
} ]
}, {
c: [{
v: "February" + " 2017"
}, {
v: 13
}]
}, {
c: [{
v: "March" + " 2017"
}, {
v: 24
}
]
}, {
c: [{
v: "April" + " 2017"
}, {
v: 24
}
]
}, {
c: [{
v: "May"+ " 2017"
}, {
v: 18
}
]
}, {
c: [{
v: "June"+ " 2017"
}, {
v: 21
}
]
}, {
c: [{
v: "July"+ " 2017"
}, {
v: 24
}
]
}, {
c: [{
v: "August"+ " 2017"
}, {
v: 14
}
]
}, {
c: [{
v: "September"+ " 2017"
}, {
v: 4
}
]
}, {
c: [{
v: "October"+ " 2017"
}, {
v: 34
}
]
}]
};
chart1.options = {
"title": "Title goes here",
"colors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"defaultColors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"isStacked": "true",
"fill": 20,
focusTarget: 'category',
"displayExactValues": true,
"vAxis": {
"title": "Sales unit",
"gridlines": {
"count": 10
}
},
"hAxis": {
slantedText : "true",
},
};
$scope.myChart = chart1;
});
In the above code i'm using v: "January" + " 2017" , i want to show only first part i.e.,January to be displayed on h-axis and January 2017 on the tooltip when mouse over on the bar(same thing february,march..on the h-axis and on the tooltip show complete text for the individual bars).
you could use a real date for the column value
this will allow hAxis.format and hAxis.ticks for the axis labels
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var data = new google.visualization.DataTable({
"cols": [{
id: "month",
label: "Month",
type: "date"
}, {
id: "laptop-id",
label: "Laptop",
type: "number"
} ],
"rows": [{
c: [
{
v: new Date(2017, 0, 1),
f: "January 2017"
},
{v: 119}
]
}, {
c: [
{
v: new Date(2017, 1, 1),
f: "February 2017"
},
{v: 022}
]
}, {
c: [
{
v: new Date(2017, 2, 1),
f: "March 2017"
},
{v: 033}
]
}, {
c: [
{
v: new Date(2017, 3, 1),
f: "April 2017"
},
{v: 044}
]
}, {
c: [
{
v: new Date(2017, 4, 1),
f: "May 2017"
},
{v: 055}
]
}, {
c: [
{
v: new Date(2017, 5, 1),
f: "June 2017"
},
{v: 066}
]
}, {
c: [
{
v: new Date(2017, 6, 1),
f: "July 2017"
},
{v: 077}
]
}, {
c: [
{
v: new Date(2017, 7, 1),
f: "August 2017"
},
{v: 088}
]
}, {
c: [
{
v: new Date(2017, 8, 1),
f: "September 2017"
},
{v: 099}
]
}, {
c: [
{
v: new Date(2017, 9, 1),
f: "October 2017"
},
{v: 010}
]
}]
});
options = {
"title": "Title goes here",
"colors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"defaultColors": ['#0000FF', '#009900', '#CC0000', '#DD9900'],
"isStacked": "true",
"fill": 20,
focusTarget: 'category',
"displayExactValues": true,
"vAxis": {
"title": "Sales unit",
"gridlines": {
"count": 10
}
},
"hAxis": {
slantedText : "true",
format: "MMM"
}
};
options.hAxis.ticks = [];
for (var i = 0; i < data.getNumberOfRows(); i++) {
options.hAxis.ticks.push(data.getValue(i, 0));
}
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
chart.draw(data, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

group and restructure json data using javascript [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have this data where I don't have control to format or do any changes
//input json data
[
{
"Breaks":[
{"points":12,"points_total":12,"average":8.0,"faults":[]},
{"points":17,"points_total":29,"average":11.6,"faults":[]},
{"points":6,"points_total":35,"average":11.6667,"faults":[]},
{"points":8,"points_total":43,"average":10.75,"faults":[]},
{"points":14,"points_total":57,"average":11.4,"faults":[]},
],
"team_name":"King Sports"
},
{
"Breaks":[
{"points":18,"points_total":18,"average":15.4286,"faults":[]},
{"points":2,"points_total":20,"average":10.0,"faults":[]},
{"points":7,"points_total":27,"average":9.0,"faults":[]},
{"points":9,"points_total":36,"average":9.0,"faults":[]},
{"points":4,"points_total":40,"average":8.0,"faults":[]},
{"points":4,"points_total":44,"average":7.33333,"faults":[]},
{"points":4,"points_total":48,"average":6.85714,"faults":[]},
{"points":8,"points_total":56,"average":7.0,"faults":[]},
{"points":1,"points_total":57,"average":6.33333,"faults":[]},
{"points":6,"points_total":63,"average":6.3,"faults":[]},
{"points":3,"points_total":66,"average":5.82353,"faults":[]},
{"points":6,"points_total":72,"average":6.0,"faults":[]},
{"points":7,"points_total":79,"average":6.07692,"faults":[]},
{"points":3,"points_total":82,"average":5.85714,"faults":[]},
{"points":0,"points_total":82,"average":5.65517,"faults":[]}
],
"team_name":"Lion Sports"
}
]
So, I need to rebuild/restructure it to get following result.
There will be 20 "Breaks" if no value found in "Breaks" till it reaches to 20 then it should have "null" values.
//the result what i wanted = output expected
[
['Breaks', 'King Sports', 'Lion Sports'],
['1', 12, 18],
['2', 29, 20],
['3', 35, 27],
['4', 43, 36],
['5', 57, 40],
['6', null, 44],
['7', null, 48],
['8', null, 56],
['9', null, 57],
['10', null, 63],
['11', null, 66],
['12', null, 72],
['13', null, 79],
['14', null, 82],
['15', null, null],
['16', null, null],
['17', null, null],
['18', null, null],
['19', null, null],
['20', null, null]
]
You could generate the result array first and the put the values in.
var data = [{ Breaks: [{ points: 12, points_total: 12, average: 8.0, faults: [] }, { points: 17, points_total: 29, average: 11.6, faults: [] }, { points: 6, points_total: 35, average: 11.6667, faults: [] }, { points: 8, points_total: 43, average: 10.75, faults: [] }, { points: 14, points_total: 57, average: 11.4, faults: [] }], team_name: "King Sports" }, { Breaks: [{ points: 18, points_total: 18, average: 15.4286, faults: [] }, { points: 2, points_total: 20, average: 10.0, faults: [] }, { points: 7, points_total: 27, average: 9.0, faults: [] }, { points: 9, points_total: 36, average: 9.0, faults: [] }, { points: 4, points_total: 40, average: 8.0, faults: [] }, { points: 4, points_total: 44, average: 7.33333, faults: [] }, { points: 4, points_total: 48, average: 6.85714, faults: [] }, { points: 8, points_total: 56, average: 7.0, faults: [] }, { points: 1, points_total: 57, average: 6.33333, faults: [] }, { points: 6, points_total: 63, average: 6.3, faults: [] }, { points: 3, points_total: 66, average: 5.82353, faults: [] }, { points: 6, points_total: 72, average: 6.0, faults: [] }, { points: 7, points_total: 79, average: 6.07692, faults: [] }, { points: 3, points_total: 82, average: 5.85714, faults: [] }, { points: 0, points_total: 82, average: 5.65517, faults: [] }], team_name: "Lion Sports" }],
result = data.reduce(function (r, a, i) {
r[0][i + 1] = a.team_name;
a.Breaks.forEach(function (b, j) {
r[j + 1][i + 1] = b.points_total;
});
return r;
}, function (length) {
var a = Array.apply(null, { length: length + 1 }).map(function (_, i) { return [(i || 'Breaks').toString(), null, null] });
return a;
}(20));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories