Reactjs : how to reduce the array of objects to get the sum - reactjs

I have the array of objects and I want to group by description with the sum of credit. I tried with my code, but it doesn't work. What's wrong with it?
My Code:
var result1=[]
entries.reduce((res, value) => {
if (!res[value.description]) {
res[value.description] = {description: value.description, credit: 0}
result1.push(res[value.description])
}
res[value.description].credit= (parseFloat(value.credit) +
parseFloat(res[value.description].credit)).toFixed(2)
return res
}, {});
let analysisByDescStr = result1.map((str) => (
<div>
{str.description|| ""} =
{str.credit|| ""}
</div>
));
Array pf objects:
{description: 'GOOGLE *Google', credit: '1.99', category: 'TELECOM'}
{description: 'AMZN Mktp #0998', credit: '20.65', category: 'MERCHANDISE'}
{description: 'AMZN Mktp #06778', credit: '70.68', category: 'MERCHANDISE'}
{description: 'OLIVE YOUNG', credit: '60.03', category: 'MERCHANDISE'}
{description: 'SAFEWAY #0982', credit: '22.97', category: 'GROCERY'}
{description: 'PEET'S #11702', credit: '7.05', category: 'COFFEE'}
{description: 'SAFEWAY #0983', credit: '20.00', category: 'GROCERY'}
{description: 'AMZN Mktp #0234', credit: '-18.62', category: 'MERCHANDISE'}
My Expected Result :
AMZN Mktp=72.71
GOOGLE *Google=1.99
OLIVE YOUNG=60.03
PEET'S=7.05
SAFEWAY=42.97

You can use reduce and apply whatever transformation you need to your item.description to match your expected labels
const result = list.reduce((acc, item) => {
const label = item.description.substring(0, 7);
return {
...acc,
[label]: (acc[label] ?? 0) + Number(item.credit)
}
}, {})

Related

how to convert a key/value object into an array of objects grouped by number of elements with javascript

how to convert an object into an array of objects following the example below
const obj = { "banks": 66.22, "desk": 40.40, "manager": 80.03, "totalBanks": 213", "totalDesk": 413", "totalManager": 113" }
the objective is that this object from above, is in this format below
const arra =[{title: "banks", quantity: 66.22, totalBanks: 212}, {title: "desk", quantity: 400, totalDesk: 413}, {title: "manager", quantity: 80.03, totalManager: 113}]
I am using this approach below with no expected success
Object.entries(obj).map(([key, value]) => ({key, value })).map(val => ({
title: val,
quantity: percent(val),
total: total(val),
})
function percent(val){
if(val.key === "banks") {
return val.value
}
}
function total(val){
if(val.key === "totalBanks") {
return val.value
}
}

Create nested JSON object fails

I am trying to create a nested JSON object using NodeJS. I am getting data from the JIRA software server and trying to map to my application's schema. Below is my application's schema.
schema:
Product:
_id: ObjectId
categories: [Category]
backlog: [Section]
Category:
_id: ObjectId
name: String
color: String
Section:
_id: ObjectId
title: String
backlogItems: [BacklogItem]
BacklogItem:
_id: ObjectId
productId: ObjectId
title: String
description: String
category: Category
acceptanceCriteria: [AcceptanceCriterion]
tasks: [Task]
notes: [Note]
I want to create one category for tasks. For example, if there are two or more issues from JIRA of type "Epic", I want to create only one category and then I want to create an array of BacklogItems but it is giving me below error:
categories: [Category], Category is not defined
Below is what I am trying to do:
function parseResponse(body) {
var data = JSON.parse(body);
result.product = {
id: ObjectID(),
categories: [Category],
backlog: [Section]
};
for (var i = 0; i < data.issues.length; i++) {
var color;
var categoryName;
switch (data.issues[i].fields.issuetype.name) {
case "Story":
color = "green";
break;
case "Epic":
color = "purple";
break;
case "Task":
color = "blue";
break;
case "Bug":
color = "red";
break;
}
var uniqeCategory = [
...new Set(data.issues.map(x => x.fields.issuetype.name))
];
if (uniqeCategory[i] !== data.issues[i].fields.issuetype.name) {
categoryName = uniqeCategory[i];
} else {
categoryName = data.issues[i].fields.issuetype.name;
}
console.log(uniqeCategory);
result.product.backlog.push({
id: ObjectID(),
title: "importer",
backlogItem: []
});
result.product.backlog.backlogItem.push({
id: data.total,
productId: result.product.id,
title: data.issues[i].fields.summary,
description: data.issues[i].fields.description,
category: data.issues[i].fields.issuetype.name,
acceptanceCriteria: [],
tasks: [],
notes: []
});
Can somebody try to tell me what I am doing wrong and How can I create such an object?
PS: I just started working with NodeJS and trying to learn it by doing it.
After some efforts, I tried to create an object. Below is my code.
for (var j = 0; j < issue.fields.attachment.length; j++) {
var note = {
_id: ObjectID(),
createdAt: issue.fields.attachment[j].created,
content: issue.fields.attachment[j].filename,
attachmentUrl: issue.fields.attachment[j].content,
attachmentPreviewUrl: issue.fields.attachment[j].thumbnail
};
notesArray.push(note);
}
/* Creating seaparate notes by taking comments from each JIRA issue and put it in form of note */
for (var k = 0; k < issue.fields.comment.comments.length; k++) {
var note = {
_id: ObjectID(),
createdAt: issue.fields.comment.comments[k].created,
content: issue.fields.comment.comments[k].body,
attachmentUrl: "",
attachmentPreviewUrl: ""
};
notesArray.push(note);
}
/* Creating backlog items */
result.product.backlog.push({
_id: ObjectID(),
productId: result.product._id,
title: issue.fields.summary,
description: issue.fields.description,
category: issue.fields.issuetype.name,
acceptanceCriteria: [],
tasks: [],
notes: notesArray
});
console.log("final", result.product);
});

AngularJS ng-repeat and indexOf() to check objects

I have two json objects (data1 and data2) that have related information. Namely, both objects have properties (arrays) which in turn can have identical data. So, I am trying to figure out how to display those data with highlighting them properly, i.e. identical data with green color and non-identical with red color. Somehow it wrongly highlights all data with red color.
Here is the html:
<ul>
<li ng-repeat="item in vm.data2.features"
ng-class="vm.data1.features.indexOf(item) !== -1 ? 'check' : 'uncheck'">
<span ng-bind="item.id"></span>
</li>
</ul>
and objects:
vm.data1 = {
id: '4569',
name: 'Given data',
features: [
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
vm.data2 = {
id: '1305',
name: 'Base data',
features: [
{id: "TEST_BP", desc: 'smth'},
{id: "TEST_TEXT2", desc: 'smth12'},
{id: "TEST_PPP", desc: 'smthsmthsmth'},
{id: "TEST_TEXT1", desc: 'blahblah'},
{id: "TEST_ECASH", desc: "somelongtexthere"}
]
};
The full demo is here.
Any help would be appreciated.
Indexof() method will look for similarity in object references not the id itself. findIndex() method can help you here instead.
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
And in html
<li ng-repeat="item in vm.data2.features"
ng-class="vm.hasFeature(item) > -1 ? 'check' : 'uncheck'">
vm.hasFeature = function(item){
var hasElements= vm.data1.features.findIndex(function(e){
return e.id == item.id;
});
console.log(item, hasElements);
return hasElements;
}
CodePen Link: https://codepen.io/anon/pen/ewgLBN?editors=1010
None of the objects will be the same because indexOf(item) will compare object references of item. You'll need to do a deep equals comparison of the items.
i.e.
{id: "TEST_TEXT2", desc: 'smth12'} === {id: "TEST_TEXT2", desc: 'smth12'} // false
vm.data1.features[0] === vm.data1.features[1] // false
Example using lodash would be something like:
_.some(vm.data1.features, otherItem => _.isEqual(item, otherItem))
Because
_.isEqual(vm.data1.features[0], vm.data2.features[1]) // true
Docs for Lodash:
_.some
_.isEqual

Mongodb - Create entry to a extisting collection field array

So I have a problem with my var array to add a new chapter, how would I go about this would I have to do this:
array.push({
chapter: [
{
id: 2,
title: 'adsf',
content: '',
authorNotes: 'asdf'
}
]
});
RiTest.ts
import * as mongoose from 'mongoose';
const Scheme = mongoose.Schema;
export const RiTestScheme = new Scheme({
novelName: String,
novelAuthor: String,
novelCoverArt: String,
novelTags: Array,
chapters: [
{
id: Number,
title: String,
content: String,
authorNotes: String
}
]
});
export class RiTestController {
public addChapter(callback: (data) => void) {
var chapterInfoModel = mongoose.model('ChaptersTest', RiTestScheme);
var array = [
{
chapter: [
{
id: 0,
title: 'prolog',
content: 'conetntt is empty',
authorNotes: 'nothing is said by author'
},
{
id: 1,
title: 'making a sword',
content: 'mine craft end chapter',
authorNotes: 'nothing'
}
]
}
];
let newChapterInfo = new chapterInfoModel(array);
newChapterInfo.save((err, book) => {
if (err) {
return callback(err);
} else if (!err) {
return callback(book);
}
});
}
}
This doesn't work, var array doesn't get saved into let newChapterInfo = new chapterInfoModel(array); what I am trying to do add another chapter to array.chapter but the array doesn't get recognized in the chapterInfoModel() how would I fix this array and add an item to the array to create a new entry into this existing collection
thank for taking your time to answer my question.
You are trying to insert array of document to your collections, That the reason its not inserting into your collection.
Document.prototype.save() will insert only one document to your collection depends on your definition. So to insert chapter here is the code below,
//array as Object
var array = {
chapter: [
{
id: 0,
title: 'prolog',
content: 'conetntt is empty',
authorNotes: 'nothing is said by author'
},
{
id: 1,
title: 'making a sword',
content: 'mine craft end chapter',
authorNotes: 'nothing'
}
]
};
//Push to your chapter array
array.chapter.push({
id: 2,
title: 'adsf',
content: '',
authorNotes: 'asdf'
});
let newChapterInfo = new chapterInfoModel(array);

AngularJS: GroupBy and show items

I've got an application where I retreive the information of some objects (into an array). That array would have the following structure:
$scope.items = [
{
id: 23289323,
event: {
id: 972823,
name: 'Event A name',
datetime: '2017-02-01 13:45',
},
player: {
id: 58392,
name: 'Player A name'
},
team: {
id: 38839,
name: 'Team A'
},
datetime: '2017-02-03 22:23'
},
{
id: 482273784,
event: {
id: 972823,
name: 'Event A name',
datetime: '2017-02-01 13:45',
},
player: {
id: 2989273,
name: 'Player B name'
},
team: {
id: 2323434,
name: 'Team B'
},
datetime: '2017-02-03 22:23'
},
{
id: 283273939,
event: {
id: 23092803,
name: 'Event B name',
datetime: '2017-02-01 13:45',
},
player: {
id: 58392,
name: 'Player A name'
},
team: {
id: 38839,
name: 'Team A'
},
datetime: '2017-02-03 22:23'
}
...
]
What I'd like
I'd like to be able to have two lists.
On the left, a list of some customizable groupingBy AngularJS filter. So, I can specify "group it by player" and it shows, on this left list, a list of the players with some information (for example, showing the player's name).
On the right, when I select a specific player, show the items that have this player associated.
What I've tried
<li data-ng-repeat="(key, value) in Ctrl.items | groupBy: 'event.id'">
{{key}}<br/>{{value}}
</li>
What I get
23289323
{id: 23289323,event: {id: 972823,name: 'Event name',datetime: '2017-02-01 13:45',}, player: {id: 58392, name: 'Player name'}, team: { id: 38839,name: 'Team A'}, datetime: '2017-02-03 22:23'}
So, I'm getting the whole item object, but I've not found any way of getting the item that I'm groupBying. Because, right now, if there are 3 items with that event.id I get three <li></li> in stead of only one (the one of the event object).
What I ask
Is there any way of using AngularJS groupBy filter and getting in return the (whole) object that is specifying the grouping?
Remember that the groupBy key can be changed by the user.
If you need any further information, please let me know.
Thank you!
I think I've made it through a custom filter. I'm not sure if it's the best way, so if anyone has another solution, please post it!
This is the code of the filter:
(function(){
angular.module("AppModule").filter('groupByGrouped', function() {
return function(list, groupedElement) {
var result = [];
var used_elements = [];
var ref_item;
var ref_check;
// Loop through every list item
angular.forEach(list, function(item){
// We take the object we want to group by inside the item
ref_item = item[groupedElement];
// If it exists
if(ref_item !== undefined){
if(ref_item.id !== undefined){
// If it has an ID, we take the ID to make it faster.
ref_check = ref_item.id;
}else{
// Otherwise, we identify the specific object by JSON string (slower method)
ref_check = JSON.stringify(ref_item);
}
// If it does not exist yet
if(used_elements.indexOf(ref_check) == -1){
// We add it to the results
result.push(ref_item);
// And we add it to the already used elements so we don't add it twice
used_elements.push(ref_check);
}
}else{
// Otherwise we log it into our console
console.warn("The key '"+groupedElement+"' inside the specified item in this list, does not exist.");
}
});
return result;
};
});
})();
This will return the whole object. So our HTML would be something like:
<ul>
<li data-ng-repeat="(key, obj) in Ctrl.items | groupByGrouped: 'event'">
<span class="object_id">{{obj.id}}</span>
</li>
</ul>
Or even with a directive (not tested, but should work aswell):
<ul>
<li data-ng-repeat="(key, obj) in Ctrl.items | groupByGrouped: 'event'">
<obj_directive ourobject="obj"></obj_directive>
</li>
</ul>

Resources