javascript how to count the object and combin - javascript

I get the data from database like this:
var json = [
{
name: "one",
roles: [
{ role: "admin",state: 1 },
{ role: "operator",state: 1 },
{ role: "admin",state: 1 }
]
},
{
name: "two",
roles: [
{ role: "admin2",state: 0 },
{ role: "operator",state: 1 },
{ role: "admin",state: 1 }
]
}
];
And I want to become this
=>
var json = [
{
name: "one",
roles:[...],
data: [
{ "admin": 2,"eable": 2,"disable":0 },
{ "operator": 1,"eable": 1,"disable":0}
]
},
{
name: "two",
roles:[...],
data: [
{ "admin": 1,"eable": 0,"disable":1 },
{ "admin2": 1,"eable": 1,"disable":0},
{ "operator": 1,"eable": 1,"disable":0}
]
}
];
I'm getting stuck now, don't know what to do,please help.
Here is what I tried:
json.forEach(function(v,k){
var ret = {
"enable":0,
"disable":0
}
json[k]['data'] = [];
json[k]['roles'].forEach(function(v,k){
json[k]['data'].push( v['role'] );
})
});
http://jsfiddle.net/B9XkX/1/

This is a lot to chew on because the data structure is weird but bear with me:
result = json.map(function(obj){
// we can use map here to transform each object, whatever we return will
// go into the result array.
var roles = obj.roles.reduce(function(memo, item){
// we need to turn a role object into a data object
// but because we are counting the number of eable
// and disable states we need to make a discreet object
// that can hold the numbers without worrying about the
// final data structure.
memo[item.role] = memo[item.role] || {};
memo[item.role].eable = memo[item.role].eable || 0;
memo[item.role].disable = memo[item.role].disable || 0;
// we initialize the memo object if we haven't seen the
// role before.
if (item.state === 1) {
// we count eable for one state
memo[item.role].eable += 1;
} else if (item.state === 0) {
// we count disable for the other state
memo[item.role].disable += 1;
}
return memo;
}, {});
// now the roles object looks something like this:
/**
* {
* admin: {eable: 2, disable: 0},
* operator: {eable: 1, disable: 0}
* }
**/
return {
name: obj.name,
roles: obj.roles,
data: Object.keys(roles).map(function(key){
// now we need to turn the roles object back into an array, so we use
// Object.keys method to turn the keys on the roles object into an array
// and we use map again to setup an object that we will use instead.
var item = {};
item[key] = 1; // {admin: 1}
item.eable = roles[key].eable; // {admin:1, eable: 2}
item.disable = roles[key].disable; // {admin:1, eable: 2, disable: 0}
return item;
})
}
});

Related

Update an array based on the value of object

Iam having an array of object named finalArr and and object named replaceJsonData. If replaceJsonData contains add =1 , then value of REQUEST_TYPE in finalArr should also become 1
finalArr = [{
REQUEST_TYPE: 'add',
TIMESTAMP: '1671636661867',
}, ]
let replaceJsonData = {
"REQUEST_TYPE": {
'add': 1,
'modify': 2
}
}
I tried like this way , but value itself is in the form a key
finalArr.map((ele)=>{
Object.entries(replaceJsonData ).forEach(
([replaceDataKey, replaceDataValue]) => {
if (ele[replaceDataKey]) {
ele[replaceDataKey]=replaceDataValue
}
}
)
});
Expected Output:
finalArr = [{
REQUEST_TYPE: 1,
TIMESTAMP: '1671636661867',
}, ]
Use the property of replaceDataValue that matches the old value of the property being updated: replaceDataValue[ele[replaceDataKey]]
let finalArr = [{
REQUEST_TYPE: 'add',
TIMESTAMP: '1671636661867',
}, ]
let replaceJsonData = {
"REQUEST_TYPE": {
'add': 1,
'modify': 2
}
};
finalArr.map((ele) => {
Object.entries(replaceJsonData).forEach(
([replaceDataKey, replaceDataValue]) => {
if (ele[replaceDataKey]) {
ele[replaceDataKey] = replaceDataValue[ele[replaceDataKey]];
}
}
)
});
console.log(finalArr);

adding another key and value to an object inside an array with JS

So I currently have a bunch of objects inside an array like below. However, I'm now trying to write a function that allows me to add another key|value into the object that was added last.
My current idea is using the arrayname.length - 1 to work out the position of the object within the array.
Would I need to create a temporary array to store the new object and then set (tempArray = oldArray) at the end of the function or would I concatinate them both?
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
this is the current code
let objects = [];
const addParent = (ev) =>{
ev.preventDefault();
// getting the length of the objects array
let arrayLength = objects.length;
// if the length of the array is zero - empty or one then set it to default zero
// else if there is objects stored in the array minus 1 to get the array position
if(arrayLength <= 0){
arrayLength = 0;
}else{
arrayLength = objects.length - 1;
}
//make a temporary array to be able to push new parent into an existing object
var tempObjects = []
for (var index=0; index<objects.length; index++){
}
//create a new parent object key : value
let parent = {
key: document.getElementById('key').value,
value: document.getElementById('value').value
}
//push parent object key and value into object
//objects.push(parent);
}
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('btn1').addEventListener('click', addParent);
});
There are multiple ways to do this.
Try this one
var objects = [{
name: "1"
}];
const addParent = (ev) => {
let parent = {
key: "some value",
value: "some value"
}
objects = Array.isArray(objects) ? objects : [];
let lastObjectIndex = objects.length - 1;
lastObjectIndex = lastObjectIndex > -1 ? lastObjectIndex : 0
objects[lastObjectIndex] = { ...objects[lastObjectIndex],
...parent
}
}
I think You want to add new value to last object of the array
Method 1
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
state[state.length - 1].newKey = "value"
console.log(state)
Method 2
const state = [
{
userId: 1,
},
{
Name: name,
},
{
age: 52,
},
{
title: "et porro tempora",
}]
// 1st method
state[state.length - 1] = {
...state[state.length - 1] ,
newKey : "value"
}
console.log(state)
You can probably use something like this:
const a = [
{ "a" : "a" },
{ "b" : "b" }
]
const c = a.map((obj, index) => {
if (index === a.length -1) {
return { ...obj, newProp: "newProp" }
}
return obj;
});
console.log(c)
This will add property on the last object using spread operator, you can look it up if you are new to JS but basically it will retain all the existing property and add the newProp to the object

Create unique values from duplicates in Javascript array of objects

I have an array of duplicated objects in Javascript. I want to create an array of unique objects by adding the index of occurrence of the individual value.
This is my initial data:
const array= [
{name:"A"},
{name:"A"},
{name:"A"},
{name:"B"},
{name:"B"},
{name:"C"},
{name:"C"},
];
This is expected end result:
const array= [
{name:"A-0"},
{name:"A-1"},
{name:"A-2"},
{name:"B-0"},
{name:"B-1"},
{name:"C-0"},
{name:"C-1"},
];
I feel like this should be fairly simple, but got stuck on it for a while. Can you please advise how I'd go about this? Also if possible, I need it efficient as the array can hold up to 1000 items.
EDIT: This is my solution, but I don't feel like it's very efficient.
const array = [
{ name: "A" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
const sortedArray = _.sortBy(array, 'name');
let previousItem = {
name: '',
counter: 0
};
const indexedArray = sortedArray.map((item) => {
if (item.name === previousItem.name) {
previousItem.counter += 1;
const name = `${item.name}-${previousItem.counter}`;
return { name };
} else {
previousItem = { name: item.name, counter: 0};
return item;
}
});
Currently you are sorting it first then looping over it, which may be not the most efficient solution.
I would suggest you to map over it with a helping object.
const a = [{name:"A"},{name:"A"},{name:"A"},{name:"B"},{name:"B"},{name:"C"},{name:"C"},], o = {};
const r = a.map(({ name }) => {
typeof o[name] === 'number' ? o[name]++ : o[name] = 0;
return { name: `${name}-${o[name]}` };
});
console.log(r);
Keep a counter, and if the current name changes, reset the counter.
This version mutates the objects. Not sure if you want a copy or not. You could potentially sort the array by object name first to ensure they are in order (if that's not already an existing precondition.)
const array = [
{ name: "A" },
{ name: "A" },
{ name: "A" },
{ name: "B" },
{ name: "B" },
{ name: "C" },
{ name: "C" },
];
let name, index;
for (let i in array) {
index = array[i].name == name ? index + 1 : 0;
name = array[i].name;
array[i].name += `-${index}`;
}
console.log(array);
Another way, if you don't want to sort, and don't want to mutate any objects, is to use a map and keep track of the current index for each object.
const array = [
// NOTE: I put the items in mixed up order.
{ name: "A" },
{ name: "C" },
{ name: "A" },
{ name: "B" },
{ name: "A" },
{ name: "C" },
{ name: "B" },
];
let index = {};
let next = name => index[name] = index[name] + 1 || 0;
let result = array.map(obj => ({ ...obj, name: obj.name + '-' + next(obj.name) }));
console.log(result);

Remove parent object and child object if value is undefined using Array.filter(?)

Question:
How can I removal all emailAddress that are empty, and if there are no emailAddresses for an approval, remove that approval too.
My current solution will remove approvals when emailAddress completely empty. But not when two emailAddresses are present and one is empty (see script output vs. expected output)
var request = {
approvals: [
{
type: 'media',
emailAddresses: [
{emailAddress: 'frank#gmail.com'},
]
},
{
type: 'other',
emailAddresses: [
{emailAddress: ''},
]
},
{
type: 'scope',
emailAddresses: [
{emailAddress: 'kelly#yahoo.com'},
{emailAddress: ''},
]
}
]
}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
let output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
// EXPECTED OUTPUT:
// approval: [
// {
// type: 'media',
// emailAddresses: [
// {emailAddress: 'frank#gmail.com'},
// ]
// },
// {
// type: 'scope',
// emailAddresses: [
// {emailAddress: 'kelly#yahoo.com'},
// ]
// }
// ]
// }]
Live Code
You are not replacing approval.emailAddresses in your code - you should use:
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
See demo below:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var filterOutEmptyEmails = (approval) => {
approval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
if(approval.emailAddresses.length){
return true;
}
}
var output = request.approvals.filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
EDIT:
Another proposal without mutating the input array - using Array.prototype.reduce to create a new array:
var request={approvals:[{type:'media',emailAddresses:[{emailAddress:'frank#gmail.com'},]},{type:'other',emailAddresses:[{emailAddress:''},]},{type:'scope',emailAddresses:[{emailAddress:'kelly#yahoo.com'},{emailAddress:''},]}]};
var output = request.approvals.reduce(function(p,c){
// creates a shallow copy
var elem = Object.assign({},c);
// replaces the reference to request.approvals by the new array created by the filter
elem.emailAddresses = elem.emailAddresses.filter(x => !!x.emailAddress);
if(elem.emailAddresses.length != 0)
p.push(elem);
return p;
},[]);
// console.log(request.approvals);
console.log(output);
.as-console-wrapper{top:0;max-height:100%!important;}
Possible "non mutation" solution could be like this
var request = {approvals: [{type: 'media',emailAddresses: [{emailAddress: 'frank#gmail.com'},]},{type: 'other',emailAddresses: [{emailAddress: ''},]},{type: 'scope', emailAddresses: [{emailAddress: 'kelly#yahoo.com'},{emailAddress: ''},]}]}
const filterOutEmptyEmails = (approval) => {
if(approval.emailAddresses.filter(x => !!x.emailAddress).length){
return true;
}
}
const output = request.approvals.map(approval => {
const filteredAproval = approval;
filteredAproval.emailAddresses = approval.emailAddresses.filter(x => !!x.emailAddress);
return filteredAproval
}).filter(filterOutEmptyEmails);
console.log(JSON.stringify(output));
console.log(JSON.stringify(request));
Without mutation (with lots of ES6/7 sugar):
const filteredApprovals = request.approvals.reduce((acc, approval) => {
const filteredEmailAddresses = approval.emailAddresses.filter(item => item.emailAddress);
return (filteredEmailAddresses.length > 0) ? [...acc, { ...approval, emailAddresses: filteredEmailAddresses }] : acc;
}, []);
Fiddle: https://jsfiddle.net/free_soul/hndjbce3/

Create object array by pushing variables?

I am trying to create something like
var[1] = {object1, object2};
var[2] = {object1, object3);
Or something like that so that I can loop over each result and get all the objects associated with that key. The problem is I am either really tried or something because I can't seem to figure out how to do that.
In PHP I would do something like
$var[$object['id']][] = object1;
$var[$object['id']][] = object2;
How can I do something like that in Javascript?
I have a list of object elements, that have a key value called id and I want to organize them all by ID. Basically...
[0] = { id: 2 },
[1] = { id: 3 },
[2] = { id: 2 },
[3] = { id: 3 }
And I want to have them organized so it is like
[0] = { { id: 2 }, { id: 2 } }
[1] = { { id: 3 }, { id: 3} }
var indexedArray = [];
for(var key in myObjects) {
var myObject = myObjects[key];
if(typeof(indexedArray[myObject.id]) === 'undefined') {
indexedArray[myObject.id] = [myObject];
}
else {
indexedArray[myObject.id].push(myObject);
}
}
console.log(indexedArray);
http://jsfiddle.net/2fr4k/
Array is defined by square brackets:
var myArray = [{ "id": 2 }, { "id": 3 }];
What you had is not a valid syntax.
Using ECMA5 methods, you could do something like this.
Javascript
var d1 = [{
id: 2
}, {
id: 3
}, {
id: 2
}, {
id: 3
}],
d2;
d2 = d1.reduce(function (acc, ele) {
var id = ele.id;
if (!acc[id]) {
acc[id] = [];
}
acc[id].push(ele);
return acc;
}, {});
d2 = Object.keys(d2).map(function (key) {
return this[key];
}, d2);
console.log(JSON.stringify(d2));
Output
[[{"id":2},{"id":2}],[{"id":3},{"id":3}]]
On jsFiddle

Categories

Resources