I want to remove TextRow and add a string(true) to JSON in NodeJs. I have added below my code.
NodeJs Code:
function groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
let key = obj[property]
if (!acc[key]) {
acc[key] = []
}
acc[key].push(obj)
return acc
}, {})
}
group data :
[
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
TextRow { name: '/sales', email: '111#gmail.com' },
TextRow { name: '/sales', email: '222#gmail.com' },
TextRow { name: '/sales', email: '333#gmail.com' },
TextRow { name: '/sales', email: '444#gmail.com' },
TextRow { name: '/finance', email: '333#gmail.com' },
TextRow { name: '/finance', email: '444#gmail.com' },
]
My output:
{
'/products': [
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
],
'/sales': [
TextRow { name: '/products', email: '111#gmail.com' },
TextRow { name: '/products', email: '222#gmail.com' },
TextRow { name: '/products', email: '333#gmail.com' },
TextRow { name: '/products', email: '444#gmail.com' },
],
'/products': [
TextRow { name: '/products', email: '333#gmail.com' },
TextRow { name: '/products', email: '444#gmail.com' },
],
}
Output Should be:
{
'/products': [
{
'111#gmail.com': true,
'222#gmail.com': true,
}
],
'/sales': [
{
'111#gmail.com': true,
'222#gmail.com': true,
'333#gmail.com': true,
'444#gmail.com': true,
}
],
'/finance': [
{
'333#gmail.com': true,
'444#gmail.com': true,
}
]
}
Instead of pushing the entire row, you want to create a new object. I'm not quite sure why your final output is an array with a single object though or why there is a true for each email.
const key = obj[property];
if (!acc[key]) {
acc[key] = [{}];
}
acc[key][0][obj.email] = true;
return acc;
Doing something like this will result in an object whose keys are the name and the values are each an array with a single object whose keys are the email addresses.
Here is an example on how you should do it. It will give you the expected result
const list = [{
TextRow: {
name: '/products',
email: '111#gmail.com'
}
},
{
TextRow: {
name: '/products',
email: '222#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '111#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '222#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '333#gmail.com'
}
}, {
TextRow: {
name: '/sales',
email: '444#gmail.com'
}
}, {
TextRow: {
name: '/finance',
email: '333#gmail.com'
}
}, {
TextRow: {
name: '/finance',
email: '444#gmail.com'
}
},
]
const result = list.reduce((acc, x) => {
const name = x['TextRow']['name'];
const obj = {
[x['TextRow'].email]: true
};
if (acc[name]) {
acc[name].push(obj)
} else {
acc[name] = [obj];
}
return acc;
}, [])
console.log(result)
Related
I have an array of objects in the format below and would like to transform it into a new array of objects using a property as a key. The key should be unique. See shape of the object below
const mockedList = [
{
email: 'aaa#example.com',
id: '5052',
name: 'Java',
},
{
email: 'bbb#example.com',
id: '5053',
name: 'Python',
},
{
email: 'aaa#example.com',
id: '5054',
name: 'C#',
},
{
email: 'bbb#example.com',
id: '5055',
name: 'Javascript',
},
];
I would like to transform this and get an array of objects with keys and values in this format.
[
{
email: 'bbb#example.com',
languages: [
{
email: 'bbb#example.com',
id: '5055',
name: 'Javascript',
},
{
email: 'bbb#example.com',
id: '5053',
name: 'Python',
},
]
},
{
email: 'aaa#example.com',
languages: [
{
email: 'aaa#example.com',
id: '5052',
name: 'Java',
},
{
email: 'aaa#example.com',
id: '5054',
name: 'C#',
},
]
}
]
I've tried using map-reduce
const result = mockedList.reduce((r, a) => {
r[a.email] = r[a.email] || [];
r[a.email].push(a);
return r;
}, Object.create(null));
But did not get the right shape of data
You can do:
const mockedList = [{email: 'aaa#example.com',id: '5052',name: 'Java',},{email: 'bbb#example.com',id: '5053',name: 'Python',},{email: 'aaa#example.com',id: '5054',name: 'C#',},{ email: 'bbb#example.com', id: '5055', name: 'Javascript' },]
const mockedListHash = mockedList.reduce((a, c) => {
a[c.email] = a[c.email] || { email: c.email, languages: [] }
a[c.email].languages.push(c)
return a
}, {})
const result = Object.values(mockedListHash)
console.log(result)
In case you want to clean the repeated emails within languages:
const mockedList = [{email: 'aaa#example.com',id: '5052',name: 'Java',},{email: 'bbb#example.com',id: '5053',name: 'Python',},{email: 'aaa#example.com',id: '5054',name: 'C#',},{ email: 'bbb#example.com', id: '5055', name: 'Javascript' },]
const mockedListHash = mockedList.reduce((a, c) => {
a[c.email] = a[c.email] || { email: c.email, languages: [] }
a[c.email].languages.push({
id: c.id,
name: c.name,
})
return a
}, {})
const result = Object.values(mockedListHash)
console.log(result)
Here is another option with simple for loop
// Array
const mockedList = [
{
email: 'aaa#example.com',
id: '5052',
name: 'Java'
},
{
email: 'bbb#example.com',
id: '5053',
name: 'Python'
},
{
email: 'aaa#example.com',
id: '5054',
name: 'C#'
},
{
email: 'bbb#example.com',
id: '5055',
name: 'Javascript'
}
];
// Set new object
const newObj = {};
// Use regular loop
for(const el of mockedList) {
// Use email as key
// If key already exist, add info
// to it's languages array
if(newObj[el.email]) newObj[el.email].languages.push(el);
else newObj[el.email] = {
email: el.email,
languages: [el]
}
}
// Test
console.log(newObj);
// If you need just array of objects,
// without email as key, then transform it
const newArr = Object.keys(newObj).map((key) => newObj[key]);
// Test
console.log(newArr);
The point is to create new object from existing listOfStudents and homeworkResults objects that are matched by email value. The goal is to use only Javascript.
An example of new object that starts like:
{
name: 'John',
email: 'john#gmail.com',
results: [
{
topic: 'HTML Basics',
success: true
},
{
topic: 'CSS Basics',
success: false
}
]
},
{
name: 'Jane',
email: 'jane#gmail.com',
results: [
{
topic: 'HTML Basics',
success: true
},
{
topic: 'CSS Basics',
success: true
}
]
}
here is an example of my code. something is wrong with addHwResults funktion because it is not excludes hwResults for other student.
var listOfStudents = [
{ name: 'John', email: 'john#gmail.com' },
{ name: 'Jane', email: 'jane#gmail.com' }
];
var hwResults = [
{ topic: 'HTML Basics', results: [ { email: 'john#gmail.com', success: true }, { email: 'jane#gmail.com', success: true } ] },
{ topic: 'CSS Basics', results: [ { email: 'john#gmail.com', success: false }, { email: 'jane#gmail.com', success: true } ] }
];
function Stud(name, email) {
const hwResults = [];
this.addHwResult = function(topic, success) {
const result = {
topic: topic,
success: success
};
hwResults.push(result);
}
this.getHomeworkResult = function() {
return hwResults;
}
}
function Lab(studentsList){
const stud = new Stud();
this.printStudList = function() {
studentsList.forEach(el => {
console.log(stud.getHomeworkResult());
});
}
this.addHwResults = function(objGet) {
objGet.results.forEach(el => {
const resultByEmail = studentsList.find(elem => elem.email === el.email);
stud.addHwResult(objGet.topic, el.success);
});
}
}
const lab = new Lab(listOfStudents);
lab.addHwResults(hwResults[0]);
lab.addHwResults(hwResults[1]);
lab.printStudList();
wrong result looks like:
enter image description here
Maintains an object map for { [email]=>Stud objects }.
Iterate on original studentList object and use [email] as key for Stud object lookup:
var listOfStudents = [
{ name: 'John', email: 'john#gmail.com' },
{ name: 'Jane', email: 'jane#gmail.com' }
];
var hwResults = [
{ topic: 'HTML Basics', results: [ { email: 'john#gmail.com', success: true }, { email: 'jane#gmail.com', success: true } ] },
{ topic: 'CSS Basics', results: [ { email: 'john#gmail.com', success: false }, { email: 'jane#gmail.com', success: true } ] }
];
function Stud(name, email) {
const hwResults = [];
this.addHwResult = function(topic, success) {
const result = {
topic: topic,
success: success
};
hwResults.push(result);
}
this.getHomeworkResult = function() {
return hwResults;
}
}
function Lab(studentsList){
const studs = Object.fromEntries(studentsList.map(({name,email})=>[email,new Stud(name,email)]));
this.printStudList = function() {
studentsList.forEach(({name, email}) => {
console.log({ name, email, results: studs[email].getHomeworkResult()});
});
}
this.addHwResults = function(objGet) {
objGet.results.forEach(({email,success}) => {
studs[email].addHwResult(objGet.topic, success);
});
}
}
const lab = new Lab(listOfStudents);
lab.addHwResults(hwResults[0]);
lab.addHwResults(hwResults[1]);
lab.printStudList();
Creates student object map, iterates over all results and populates student results list. Unwraps object map into list.
var listOfStudents = [
{ name: 'John', email: 'john#gmail.com' },
{ name: 'Jane', email: 'jane#gmail.com' },
{ name: 'failure', email: 'wat#aol.com' },
{ name: 'tryhard', email: 'imcool#hotmail.com' }
];
var hwResults = [
{ topic: 'HTML Basics', results: [ { email: 'john#gmail.com', success: true }, { email: 'jane#gmail.com', success: true } ] },
{ topic: 'CSS Basics', results: [ { email: 'john#gmail.com', success: false }, { email: 'jane#gmail.com', success: true }, { email: 'imcool#hotmail.com', success: false } ] }
];
const stuMap = Object.fromEntries(
listOfStudents.map(x=>[x.email,{...x, results: []}]) )
hwResults.forEach( ({topic,results})=>
results.forEach( ({email,success})=>
stuMap[email].results.push({topic,success}) ))
console.log(
Object.values(stuMap)
)
I'm trying to merge objects in an array with the same id without overriding different value properties.
var arr = [{
Messages: { count: 1 },
Account: { key: 'TEST' },
id: 179,
Contact:
{
firstName: 'The Postman',
lastName: 'Team'
},
Tags: { name: 'forums', color: '#0091EA' }
},
{
Messages: { count: 1 },
Account: { key: 'TEST' },
id: 179,
Contact:
{
firstName: 'The Postman',
lastName: 'Team'
},
Tags: { name: 'defective', color: '#0091EA' }
}];
var tags = [];
for(var i=0; i<arr.length; i++){
tags = tags.concat(arr[i].Tags);
}
var result = arr[0];
result.Tags = tags;
console.log(result);
My goal is is to have the following object:
var obj =
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: [{ name: "forums", color: "#0091EA" }, { name: "defective", color: "#0091EA" }]
};
I've created a fiddle where I managed to get the desired output, but I'm sure there is a better way to do it.
http://jsfiddle.net/18mLhx7j/1/
UPDATE
Based on the answer posted by #Harun Yilmaz I was able to accomplish the same result using Lodash reduce.
I just wonder if it's a valid alternative to what he posted.
var arr = [
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "defective", color: "#0091EA" } }
];
var interactions =_.reduce(arr, function(acc, cur) {
for (let i =0; i < Object.keys(cur).length; i++) {
let key = Object.keys(cur)[i];
if (!acc[key]) {
acc[key] = cur[key];
} else if (acc[key] && !_.isArray(acc[key]) && !_.isEqual(acc[key], cur[key])) {
var obj = [];
obj.push(acc[key]);
obj.push(cur[key]);
acc[key] = obj;
} else if (acc[key] && _.isArray(acc[key])) {
acc[key].push(cur[key]);
}
}
return acc;
}, {});
console.log(interactions);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
You can use Array.reduce() to have a final object and spread operator as following
var arr = [
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "forums", color: "#0091EA" } },
{ Messages: { count: 1 },
Account: { key: "TEST" },
id: 179,
Contact: { firstName: "The Postman", lastName: "Team" },
Tags: { name: "defective", color: "#0091EA" } }
];
const finalArr = arr.reduce((acc, cur) => {
const {Tags,...Rest} = cur;
acc.Tags.push(Tags);
acc = {
...Rest,
Tags: acc.Tags
};
return acc;
},{Tags:[]});
// ^^ initial object
console.log(finalArr);
I am trying to create a function to generate an array of objects with a UUID as the key, as well as a UUID for some of the nested object ids.
Each game will be based on a mock object which I import into the file.
The function expects a sport (string) which will get assigned to a key and a quantity (number) which will determine the for loop iterations.
When using a for loop the UUID for the nested object ids are getting overridden on each iteration.
const mockGame = require('../mock-game');
const uuidv4 = require('uuid/v4');
function generateMockGames(sport, quantity) {
let games = []
for (let i = 0; i < quantity; i++) {
let game = {}
let id = uuidv4()
game[id] = {
search: mockGame.search,
query: mockGame.query,
variables: mockGame.variables,
}
game[id].search.eventId = id
game[id].search.competition.categoryName = sport
game[id].search.id = id
game[id].search.competition.categoryName = sport;
games.push(game);
}
return games;
}
const mockFootballGame = generateMockGames('football', 3);
Expected result:
[
{
'286c1911-b155-4197-bbde-64dba0b304fe': {
search: {
eventId: '286c1911-b155-4197-bbde-64dba0b304fe',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: '286c1911-b155-4197-bbde-64dba0b304fe',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
},
{
'082a46a6-4dde-433d-8011-9e94a5ee79ff': {
search: {
eventId: '082a46a6-4dde-433d-8011-9e94a5ee79ff',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: '082a46a6-4dde-433d-8011-9e94a5ee79ff',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
},
{
'ba911751-3ea3-40ab-9bec-c525ab2a07b9': {
search: {
eventId: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
}
]
Output is:
[
{
'286c1911-b155-4197-bbde-64dba0b304fe': {
search: {
eventId: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
},
{
'082a46a6-4dde-433d-8011-9e94a5ee79ff': {
search: {
eventId: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
},
{
'ba911751-3ea3-40ab-9bec-c525ab2a07b9': {
search: {
eventId: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
name: 'test name',
competition: {
categoryName: 'football'
}
},
query: {
id: 'ba911751-3ea3-40ab-9bec-c525ab2a07b9',
competition: {
categoryName: 'football'
}
},
variables: {
name: 'test name'
}
}
]
You are assigning subobjects of mockGame in your loop to the entries, without copying them. So you keep overwriting mockGame.query.id etc, with a new uuid in your loop, but then assign the mockGame.query object as a whole to your output.
I create a ticket using zendesk but I didn't know why this happens
here is node js code:
config.js
baseTicketObject: {
'comment': {
'body': null,
},
'requester': {
'name': null,
'email': null,
},
'custom_fields': [],
},
create ticket api
function createTicketObjectFromRequest(req) {
const requestBody = req.body;
console.log('requestBody', requestBody);
console.log('config.baseTicketObject', config.baseTicketObject);
const ticket = Object.assign(config.baseTicketObject, {});
//console.log('ticket', ticket);
const {
messageBody, email, name, customFields,
} = requestBody;
//console.log('ticket.custom_fields', ticket.custom_fields);
// Request must contain a name, email and body
ticket.requester.name = name;
ticket.requester.email = email;
ticket.comment.body = messageBody;
if (req.user && req.user.id) {
ticket.custom_fields.push(createCustomFieldObject(config.customFieldNameToZendeskFieldIdMapping['userId'], Number(req.user.id)));
}
Object.keys(config.customFieldNameToZendeskFieldIdMapping).forEach((fieldName) => {
if (config.customFieldNameToZendeskFieldIdMapping[fieldName] === config.customFieldNameToZendeskFieldIdMapping.userId) {
return;
}
//console.log('fieldName', fieldName);
const mappedCustomFieldId = config.customFieldNameToZendeskFieldIdMapping[fieldName];
if (mappedCustomFieldId) {
ticket.custom_fields.push(createCustomFieldObject(mappedCustomFieldId, !customFields[fieldName] ? '' : customFields[fieldName]));
}
});
return { ticket: ticket };
}
whenever I post a request the config.baseTicketObject will keep all items i pushed before like this
config.baseTicketObject { comment: { body: null },
requester: { name: null, email: null },
custom_fields: [] }
-------------------------------------
config.baseTicketObject { comment: { body: 'dgfhdgfhdgfh dgfhdfghdfg' },
requester: { name: 'test other', email: 'tranthiphuonghue96#yopmail.com' },
custom_fields:
[ { id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' } ] }
---------------------------------------------------------
config.baseTicketObject { comment: { body: 'dgfhdgfhdgfh dgfhdfghdfg' },
requester: { name: 'test other', email: 'tranthiphuonghue96#yopmail.com' },
custom_fields:
[ { id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' },
{ id: 360010481051, value: '' },
{ id: 360010510411, value: '' },
{ id: 360010406792, value: '' },
{ id: 360010511011, value: '' },
{ id: 360010511191, value: '' },
{ id: 360010920852, value: 'contact_support' } ] }
I don't know why the config.baseTicketObject like that, please help.
Reverse parameters order in Object.assing.
You have
Object.assign(config.baseTicketObject, {});
but should be
Object.assign({}, config.baseTicketObject);
Object.assign syntax
Object.assign(target, ...sources)
In your case
const ticket = Object.assign({}, config.baseTicketObject);
Edit:
Add
ticket.custom_fields = [];
after
const ticket = Object.assign({}, config.baseTicketObject);
because Object.assign create shallow copy, witch mean that ticket.custom_fields still holds reference to original array object from config.baseTicketObject.custom_fields