use lodash operators in nested properties - javascript

I have array of objects
{
"agent_name": "AgentName",
"analytics": [
{
"date": "Tue, 1 Aug 2021 00:00:00 GMT",
"intents_count":[
{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
},
{
"date": "Tue, 2 Aug 2021 00:00:00 GMT",
"intents_count":[
{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
},
... the same for the next days of month
]
}
I need to get the sum of count for each intent grouped by date.
The result should be something like this:
[10, 2, 0]
where 10 correspond to sum of count field of the intent 'intent1' during all days.

You need to first flat and select the required array "analytics". Then use groupBy and sum to get the final result.
let data = {
"agent_name": "AgentName",
"analytics": [
{
"date": "Tue, 1 Aug 2021 00:00:00 GMT",
"intents_count":[
{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
},
{
"date": "Tue, 2 Aug 2021 00:00:00 GMT",
"intents_count":[
{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
},
]
}
let flatResult = _.flatMap(data.analytics, 'intents_count');
let result = _(flatResult).groupBy('intent').map(x => _.sumBy(x, 'count'));
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

I have a high level solution to what can be done. This is not using lodash operators, but can be a good starting point.
const data = {
"agent_name": "AgentName",
"analytics": [{
"date": "Tue, 1 Aug 2021 00:00:00 GMT",
"intents_count": [{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
},
{
"date": "Tue, 2 Aug 2021 00:00:00 GMT",
"intents_count": [{
"count": 5,
"intent": "intent1"
},
{
"count": 1,
"intent": "intent2"
},
{
"count": 0,
"intent": "intent3"
},
]
}
]
}
const arr = [];
data.analytics.forEach(intentObj => {
intentObj.intents_count.forEach(obj => {
//calculating the index to store the value in array.
const index = obj.intent[6] - 1;
if (arr[index] !== undefined) {
arr[index] = arr[index] + obj.count;
} else {
arr[index] = obj.count;
}
});
});
console.log(arr);

Related

How to update the page after call Axios.patch?

I made a line change via axios.path, but after changes in db.json I constantly need to reload the page. How can I avoid this and make the data update automatically?
const submitEdits = (item) => {
axios.patch(`http://localhost:3004/item/${item.id}`, { text: editingText })
setIdItem(null);
setEditingText('')
}
My db.json
{
"item": [
{
"text": "123123123",
"id": 0,
"data": {
"year": 2012,
"day": 25,
"month": 1
}
},
{
"text": "Поступил в институт",
"id": 1,
"data": {
"year": 2007,
"day": 12,
"month": 4
}
},
{
"id": 2,
"text": "123",
"data": {
"year": 2022,
"day": 16,
"month": 5
}
}
]
}

MongoDB Month wise grouping

Can Somebody Please help in getting the last 6 months count of my given data?
This My Data
{
"_id" : ObjectId("59815d4704ca1760a45957ca"),
"ticketId" :"TCKT0HF652Y",
"createdAt" : ISODate("2020-06-02T05:03:57Z")
},
{
"_id" : ObjectId("59815d5404ca1760a45957cb"),
"ticketId" :"TCKT0HF8849A",
"createdAt" : ISODate("2020-06-02T05:04:11Z")
},
{
"_id" : ObjectId("5980191d04ca1760a45957cd"),
"ticketId" :"TCKT0H4953Z",
"createdAt" : ISODate("2020-05-01T06:00:46Z")
},
{
"_id" : ObjectId("59815d4704ca1760a45957ca"),
"ticketId" :"TCKT0HF339Y",
"createdAt" : ISODate("2020-05-02T05:03:57Z")
},
{
"_id" : ObjectId("59815d5404ca1760a45957cb"),
"ticketId" :"TCKT0HF839A",
"createdAt" : ISODate("2020-05-02T05:04:11Z")
},
{
"_id" : ObjectId("5980191d04ca1760a45957cd"),
"ticketId" :"TCKT0HF9582Z",
"createdAt" : ISODate("2020-04-01T06:00:46Z")
}
And My Query is
Tickets.aggregate([
{
$project: {
count: {$sum: 1},
month: {$month: "$createdAt"},
year: {$year: "$createdAt"},
},
},
{
$group: {
_id: {month: "$month", year: "$year"},
total: {$sum: "$count"},
},
},
])
And This is the result I am getting
"data": [
{
"_id": {
"month": 6,
"year": 2020
},
"total": 2
},
{
"_id": {
"month": 5,
"year": 2020
},
"total": 3
},
{
"_id": {
"month": 4,
"year": 2020
},
"total": 1
}
]
My Requirement is to generate the last 6 months' data irrespective of whether the month has data or not. So the result I am expecting is
"data": [
{
"_id": {
"month": 6,
"year": 2020
},
"total": 2
},
{
"_id": {
"month": 5,
"year": 2020
},
"total": 3
},
{
"_id": {
"month": 4,
"year": 2020
},
"total": 1
},
{
"_id": {
"month": 3,
"year": 2020
},
"total": 0
},
{
"_id": {
"month": 2,
"year": 2020
},
"total": 0
},
{
"_id": {
"month": 1,
"year": 2020
},
"total": 0
}
]
And can we also display month names instead of month numbers?.
I don't think you you output Months names natively in MongoDB. I suggest Moment.js library. Could be this one:
Tickets.aggregate([
{
$group: {
_id: {
month: { $month: "$createdAt" },
year: { $year: "$createdAt" }
},
total: { $sum: 1 },
},
}
]).forEach(function (row) {
print(moment.utc(row._id.year + "-" + row._id.month, "YYYY-MM").format("MMMM YYYY") + ": " + row.total);
})

How to eliminate multiple iteration

Following code gets the result below in a way that multiple iterations required. I wonder what would be the way to make it happen in a single or less iterations. Thanks in advance.
var input = [{
"ActiveMembers": [{
"Id": 101,
"Name": "alpha"
}, {
"Id": 102,
"Name": "bravo"
}],
"Contents": [{
"Id": 2001,
"RowId": "517",
"Time": "19 Jan 2017",
"ViewCount": 1124
}, {
"Id": 2002,
"RowId": "518",
"Time": "Today, 07:02 PM",
"ViewCount": 62
}],
"TotalUsers": 3,
"UsersDetails": "2 members, 1 anonymous users"
}, {
"ActiveMembers": [{
"Id": 101,
"Name": "alpha"
}, {
"Id": 103,
"Name": "charlie"
}, {
"Id": 104,
"Name": "delta"
}, {
"Id": 105,
"Name": "bravo"
}],
"Contents": [{
"Id": 2002,
"RowId": "519",
"Time": "27 Jun 2017",
"ViewCount": 4833
}, {
"Id": 2041,
"RowId": "525",
"Time": "17 Feb 2015",
"ViewCount": 24491
}],
"TotalUsers": 23,
"UsersDetails": "4 members, 19 anonymous users"
}];
var contents = Array.prototype.concat.apply([], input.map(i => i.Contents));
var activeMembers = _.uniqBy(Array.prototype.concat.apply([], input.map(i => i.ActiveMembers)), (i) => i.Id);
var totalUsers = number = _.sumBy(input, (i) => i.TotalUsers);
var userDetails = string = input.map(i => i.UsersDetails).join(' ; ');
const result = new Object();
result.Contents = contents;
result.ActiveMembers = activeMembers;
result.TotalUsers = totalUsers;
result.UserDetails = userDetails;
console.log(JSON.stringify(result));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Result
{
"ActiveMembers": [
{
"Id": 101,
"Name": "alpha"
},
{
"Id": 102,
"Name": "bravo"
},
{
"Id": 103,
"Name": "charlie"
},
{
"Id": 104,
"Name": "delta"
},
{
"Id": 105,
"Name": "bravo"
}
],
"Contents": [
{
"Id": 2001,
"RowId": "517",
"Time": "19 Jan 2017",
"ViewCount": 1124
},
{
"Id": 2002,
"RowId": "518",
"Time": "Today, 07:02 PM",
"ViewCount": 62
},
{
"Id": 2002,
"RowId": "519",
"Time": "27 Jun 2017",
"ViewCount": 4833
},
{
"Id": 2041,
"RowId": "525",
"Time": "17 Feb 2015",
"ViewCount": 24491
}
],
"TotalUsers": 26,
"UsersDetails": "2 members, 1 anonymous users;4 members, 19 anonymous users"
}
Aggregate the data in a single iteration.
let ActiveMembers = [];
let Contents = [];
let TotalUsers = 0;
let UserDetails = [];
input.forEach((item) => {
ActiveMembers = ActiveMembers.concat(item.ActiveMembers);
Contents = Contents.concat(item.Contents);
TotalUsers += item.TotalUsers;
UserDetails.push(item.UsersDetails);
});
const result = {
ActiveMembers: _.uniqBy(ActiveMembers, "Id"),
Contents: Contents,
TotalUsers: TotalUsers,
UserDetails: UserDetails.join(";")
};
console.log(JSON.stringify(result));

Filter nested JSON object with multiple arrays and store the filtered objects in an array

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);

converting unix time stamp conversion

I have an array which has time stored in Unix timestamp and number of matches played on that day,
[
{
"time": 1332547200000,
"count": 2
},
{
"time": 1332633600000,
"count": 1
},
{
"time": 1332720000000,
"count": 4
},
{
"time": 1332806400000,
"count": 4
},
...
],
I am trying to convert this into a string of elements with date format "20070101", value
for example, I should get the output in the form, "20070101, 46 \n" +20072102, 26 \n" + etc....
:)
function pad2(number) {
return (number < 10 ? '0' : '') + number
}
var ar = [{ "time": 1332547200000, "count": 2 }, { "time": 1332633600000, "count": 1 }, { "time": 1332720000000, "count": 4 }];
var output = ""
for (i=0; i<ar.length; i++) {
var d = new Date(parseInt(ar[i].time));
var year = ""+d.getFullYear();
var month = pad2(d.getMonth());
var date = pad2(d.getDate());
var output = output+year+date+month+", "+ar[i].count+"\n";
}
document.write(output);
var d = new Date(milliseconds);
var formatted = d.getFullYear()+d.getMonth()+d.getDate();
Unfortunately there doesn't seem to be any date formatting/zero padding functions in raw javascript. I'd recommend using jQuery or another library. This is the raw solution.
var data = [
{ "time": 1332547200000, "count": 2 },
{ "time": 1332633600000, "count": 1 },
{ "time": 1332720000000, "count": 4 }
];
function pad(str, n) {
if (str.length < n) {
return pad("0" + str, n);
} else {
return str
}
}
for (var i = 0; i < data.length; i++) {
var datum = data[i];
var date = new Date(datum.time);
var str = date.getFullYear()
+ pad((date.getMonth() + 1).toString(), 2)
+ pad(date.getDate().toString(), 2)
+ ", " + datum.count + " \\n";
window.alert(str);
}​
That is a JSON string and you can use $.parseJSON in jQuery:
myJSON = $.parseJSON('[{ "time": 1332547200000, "count": 2 }, { "time": 1332633600000, "count": 1 }]');
var newJSON = new Array();
var i = 0;
$.each(myJSON, function(count, line){
var newTime = new Date(parseInt(line.time));
newTime = newTime.getFullYear()+''+('0' + (newTime.getMonth()+1)).slice(-2)+''+('0' + newTime.getDate()).slice(-2);
$('#json').append(newTime+', '+line.count+'\n');
});
DEMO JSFIDDLE
Here is Your FIDDLE
FIDDLE
AND Your Code:
var a=[
{ "time": 1332547200000, "count": 2 }, { "time": 1332633600000, "count": 1 }, { "time": 1332720000000, "count": 4 }, { "time": 1332806400000, "count": 4 }, { "time": 1332892800000, "count": 5 }, { "time": 1332979200000, "count": 1 }, { "time": 1333065600000, "count": 1 }, { "time": 1333152000000, "count": 1 }, { "time": 1333324800000, "count": 2 }, { "time": 1333411200000, "count": 2 }, { "time": 1333497600000, "count": 3 }, { "time": 1333584000000, "count": 4 }, { "time": 1333670400000, "count": 3 }, { "time": 1333756800000, "count": 2 }, { "time": 1333843200000, "count": 2 }, { "time": 1333929600000, "count": 1 }, { "time": 1334102400000, "count": 9 }, { "time": 1334188800000, "count": 8 }, { "time": 1334275200000, "count": 6 }, { "time": 1334361600000, "count": 3 }, { "time": 1334448000000, "count": 2 }, { "time": 1334534400000, "count": 3 }, { "time": 1334620800000, "count": 3 }, { "time": 1334707200000, "count": 5 }, { "time": 1334793600000, "count": 4 }, { "time": 1334880000000, "count": 1 }, { "time": 1334966400000, "count": 5 }, { "time": 1335139200000, "count": 6 }, { "time": 1335225600000, "count": 3 }, { "time": 1335312000000, "count": 8 }, { "time": 1335398400000, "count": 8 }, { "time": 1335484800000, "count": 9 }, { "time": 1335571200000, "count": 4 }, { "time": 1338508800000, "count": 69 }, { "time": 1338595200000, "count": 30 }, { "time": 1338681600000, "count": 17 }, { "time": 1338768000000, "count": 70 }, { "time": 1338854400000, "count": 109 }, { "time": 1338940800000, "count": 80 }, { "time": 1339027200000, "count": 141 }, { "time": 1339113600000, "count": 94 }, { "time": 1339200000000, "count": 34 }, { "time": 1339286400000, "count": 26 }, { "time": 1339372800000, "count": 91 }, { "time": 1339459200000, "count": 166 }, { "time": 1339545600000, "count": 89 }, { "time": 1339632000000, "count": 121 }, { "time": 1339718400000, "count": 74 }, { "time": 1339804800000, "count": 48 }, { "time": 1339891200000, "count": 13 }, { "time": 1339977600000, "count": 58 }, { "time": 1340064000000, "count": 123 }, { "time": 1340150400000, "count": 110 }]
function getformateddate(date)
{
var date= new Date(date);
return date.getFullYear().toString()+date.getDate()+date.getMonth();
}
var finalString='';
for (var i=0;i<a.length;i++)
{
finalString+=getformateddate(a[i].time)+' '+a[i].count+" \\"+"n"
}
document.write(finalString)

Categories