Dynamically add objects to an array - javascript

I want to create a datasource dynamically for my table from a array of objects.
Required datasource value:
values = [
{
name: "Super Admin"
cv: 1
assessment1_title: score/status
assessment2_title: score/status
interview1_title: score/status
interview2_title: score/status
}
]
I have the following array of object:
data = {
"assessments": [
{
"id": 6,
"title": "PHP Laravel Developer",
"type": "Objective"
},
{
"id": 7,
"title": "Laravel Developer",
"type": "Objective"
}
],
"candidates": [
{
"id": 11,
"user_id": 1,
"user_name": "Super Admin",
"assessments": [
{
"id": 1,
"score": 5,
"duration": 1170,
"status": {
"id": 22,
"name": "completed"
}
},
{
"id": 2,
"score": 0,
"duration": 0,
"status": {
"id": 22,
"name": "Pending"
}
}
]
}
]
}
where the value of assessment_title will be dynamically generated from data.assessments.map(({title}) => title) and the value will be one of score and status
data.canditates.map(res => res.assessments.map(res2=> {
if res2.status.id ==22 {
value = res2.score
} else {
value = res2.status.name
}
})
);
I want to make the required datasource value. Thanks in advance

You can get the desired result by using reduce on candidates and then forEach assessments element add title and score/status.
const data = {"assessments":[{"id":6,"title":"PHP Laravel Developer","type":"Objective"},{"id":7,"title":"Laravel Developer","type":"Objective"}],"candidates":[{"id":11,"user_id":1,"user_name":"Super Admin","assessments":[{"id":1,"score":5,"duration":1170,"status":{"id":22,"name":"completed"}},{"id":2,"score":0,"duration":0,"status":{"id":22,"name":"Pending"}}]}]}
const result = data.candidates.reduce((r, c) => {
const obj = {}
obj.cv = c.user_id;
obj.name = c.user_name;
c.assessments.forEach((e, i) => {
const {score, status: {name}} = e;
const {title} = data.assessments[i];
obj[title] = e.status.id === 22 ? name : score;
})
r.push(obj)
return r;
}, [])
console.log(result)
You could also create a bit more flexible solution that will work in case you have more then two keys in original object.
const data = {"assessments":[{"id":6,"title":"PHP Laravel Developer","type":"Objective"},{"id":7,"title":"Laravel Developer","type":"Objective"}],"interviews":[{"id":1,"title":"Interview 1"},{"id":2,"title":"Interview 2"}],"candidates":[{"id":11,"user_id":1,"user_name":"Super Admin","interviews":[{"id":1,"score":3,"status":{"name":"completed"}},{"id":2,"score":0,"status":{"name":"pending"}}],"assessments":[{"id":1,"score":5,"duration":1170,"status":{"id":22,"name":"completed"}},{"id":2,"score":0,"duration":0,"status":{"id":22,"name":"Pending"}}]}]}
const result = data.candidates.reduce((r, c) => {
const obj = {}
obj.cv = c.user_id;
obj.name = c.user_name;
Object.keys(data).forEach(k => {
if(k !== 'candidates') {
data[k].forEach((e, i) => {
const {title} = e;
const {score, status: {name}} = c[k][i];
obj[title] = `${score}/${name}`
})
}
})
r.push(obj)
return r;
}, [])
console.log(result)

My solution would be something like below.
data = {
assessments: [
{
id: 6,
title: "PHP Laravel Developer",
type: "Objective"
},
{
id: 7,
title: "Laravel Developer",
type: "Objective"
}
],
candidates: [
{
id: 11,
user_id: 1,
user_name: "Super Admin",
assessments: [
{
id: 6,
score: 5,
duration: 1170,
status: {
id: 22,
name: "completed"
}
},
{
id: 7,
score: 0,
duration: 0,
status: {
id: 21,
name: "Pending"
}
}
]
}
]
};
assessments_map = data.assessments.reduce((acc, val) => {
const {id,...rest} = val;
acc[id] = rest;
return acc
}, {});
assessments_map;
a = data.candidates.map((candidate) => {
return {name: candidate.user_name,
...candidate.assessments.reduce((acc, assessment) => {
acc[assessments_map[assessment.id].title] =
assessment.status.id == 22
? assessment.score
: assessment.status.name;
return acc;
}, {})
}
});
console.log(a);

Related

Find and replace element in array on the basis of id

I have an array as follows:
[
{
"id":1,
"active":1,
"name":"paris"
},
{
"id":2,
"active":0,
"name":"london"
},
{
"id":3,
"active":1,
"name":"Australia"
},
{
"id":4,
"active":0,
"name":"india"
}
]
I have a method which recieved a object as argument. object looks something like this:
{
"id":4,
"active":0,
"name":"india"
}
In that method I want to check if element with particular id is present or not. If present I want to replace element in array with the element received in arguments. If element with that id is not found that add that element to the array. How can I do that?
you can do like this
let testArr = [
{
id: 1,
active: 1,
name: "paris",
},
{
id: 2,
active: 0,
name: "london",
},
{
id: 3,
active: 1,
name: "Australia",
},
{
id: 4,
active: 0,
name: "india",
},
];
let testObj = {
id: 4,
active: 0,
name: "india1",
};
let findIndex = testArr.findIndex((data) => data.id === testObj.id);
if (findIndex != -1) {
testArr[findIndex].active = testObj.active;
testArr[findIndex].name = testObj.name;
} else {
testArr = [...testArr, testObj];
}
console.log("testArr=>", testArr);
I'd propose the following: in any case you want to have the new object included in the given array:
Remove Object with id from array
Add new Object
Could work as following:
let testArr = [ ... ]
let testObj = { ... }
testArr = testArr.filter(element => element.id !== testObj.id)
testArr.push(testObj)
If it's necessary to keep the object in the array:
let testArr = [ ... ]
let testObj = { ... }
const foundElement = testArr.find(element => element.id === testObj.id)
if (foundElement) {
foundElement.active = testObj.active
foundElement.name = testObj.name
} else {
testArr.push(testObj)
}
you can do something like this
const update = (data, item) => {
const withId = data.reduce((res, curr) => ({
...res,
[curr.id]: curr
}), {})
withId[item.id] = item
return Object.values(withId)
}
let testArr = [
{
id: 1,
active: 1,
name: "paris",
},
{
id: 2,
active: 0,
name: "london",
},
{
id: 3,
active: 1,
name: "Australia",
},
{
id: 4,
active: 0,
name: "india",
},
];
let testObj = {
id: 4,
active: 0,
name: "india1",
};
const updated = update(testArr, testObj)
console.log(updated)

unable to change the items based on id and expected result should be in output format

unable to change the items based on id and expected result should be in output format
const items = [
{ id: 1, value: "first" },
{ id: 2, value: "second" },
{ id: 3, value: "third" }
];
const expectedOutput = [
{ id: 1, value: "first" },
{ id: 2, value: "newvalue" },
{ id: 3, value: "third" }
]
function getData(value, id) {
return items.map((_each)=> {
if(_each.id === id) {
//need to update items with id=2
}
})
}
console.log(getData("newvalue", 2))
let inputArr = {
"data": [{
"id": 1,
"value": "first",
"row": "A"
},
{
"id": 2,
"value": "second",
"row": "A"
},
{
"id": 3,
"value": "Third",
"row": "B"
},
{
"id": 4,
"value": "Fourth",
"row": "B"
}
]
}
function format(inputArr) {
let arr = []
let obj = {};
inputArr.data.forEach(el => {
obj = {
...obj,
[el.row]: [...(obj[el.row] || []) , el.value],
}
});
arr.push(obj);
return arr;
}
let outputArr = format(inputArr)
console.log(outputArr)
let expectedOutput = [{
"A": ["first", "second"]
}, {
"B": ["Third", "Fourth"]
}]
#chidananda,
Map callback should return updated item. Minor modification to your code would work!
const items = [
{ id: 1, value: "first" },
{ id: 2, value: "second" },
{ id: 3, value: "third" }
];
const expectedOutput = [
{ id: 1, value: "first" },
{ id: 2, value: "newvalue" },
{ id: 3, value: "third" }
]
function getData(value, id) {
return items.map((_each)=> {
if(_each.id === id) {
_each.value = value;
}
return _each; // Return the modified item
})
}
console.log(getData("newvalue", 2))

In an array, display an object only once if it has the same id, but still display other properties

What I would like to achieve is that I want to display fromUsers one by one, but no duplicates. So if I have 2 messages from the same John (same fromUserId), then I want this John's name to appear only once, because it's the same John with the same fromUserId. Then once I click on John's name, then I would see 2 messages (hi + hey). We cannot get rid of any objects because the message are different and I still need to display these messages. Is it possible to implement this? I am using Node.js, Mongodb, Mongoose, and React.
[
{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "hey",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
}
]
Render:
<div>
{this.state.from.map((from) => {
return <div key={from._id}>{from.fromUser}</div>;
})}
</div>
Axios get request:
axios.get('/api/getMessage', { headers: { 'X-Auth-Token': token } }).then((res) => {
this.setState({ from: res.data });
});
State in class component:
this.state = {
message: '',
from: [],
};
Uses an object map to collect messages into arrays. Resultant data in the form of:
[ { _id, fromUser, messages} ... ]
const fromCollectMessages = from =>
Object.values(from.reduce((chats,{message:m, fromUserId: _id, fromUser})=>{
chats[_id] = chats[_id] || { _id, fromUser }
chats[_id].messages = chats[_id].messages || []
chats[_id].messages.push(m)
return chats
},{}))
const data=[
{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "hey",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola2",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
},
{
"message": "hi2",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
}
]
console.log(fromCollectMessages(data))
const { Component } = React,
{ render } = ReactDOM,
el = document.getElementById('app')
class Name extends Component {
constructor(props) {
super(props)
this.state = {from: fromCollectMessages(props.from)}
}
render() {
return (
<div>
{this.state.from.map((from) => {
return <div key={from._id} style={{cursor:'pointer'}}
onClick={()=>alert(from.messages.join('\n'))}>
{from.fromUser}
</div>;
})}
</div>
)
}
}
render(<Name from={data}/>,el)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
With the given constraints, I'd assume that messages are in order. Also, if they are not then consider adding a timestamp.
Moving forwards, this json can be shown as something like this:
John: hi
John: hey
Jane: ola
But what you're asking for is:
John: hi hey
Jane: ola
Following code will help merge similar users together:
const chats = [
{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "hey",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
}
];
userChat = {};
// grouping the chat together
for (const msg of chats) {
let user = msg.fromUserId;
if (userChat[user] === undefined) {
userChat[user] = msg;
} else {
userChat[user].message += " " + msg.message;
}
}
// printing the msg out
for (const user in userChat) {
console.log("User: ", userChat[user].fromUser);
console.log("Message: ", userChat[user].message);
}
I've intentionally chosen this way so that it can be extended for multiple uses also. (just in case)
you should use reducer, adapt this code to yours:
const arr = [
{ id: 1, name: "test1", msg: 'hi1' },
{ id: 2, name: "test2", msg: 'hi2' },
{ id: 2, name: "test3", msg: 'hi3' },
{ id: 3, name: "test4", msg: 'hi4' },
{ id: 4, name: "test5", msg: 'hi5' },
{ id: 5, name: "test6", msg: 'hi6' },
{ id: 5, name: "test7", msg: 'hi7' },
{ id: 6, name: "test8", msg: 'hi8' }
];
const filteredArr = arr.reduce((acc, current) => {
const x = acc.find(item => item.id === current.id);
if (!x) {
return [...acc, current];
} else {
return acc.map(x=> x.id === current.id ? ({...x, msg: x.msg + current.msg }) : x)
}
}, []);
console.log(filteredArr)
Result:
[{
id: 1,
msg: "hi1",
name: "test1"
}, {
id: 2,
msg: "hi2hi3",
name: "test2"
}, {
id: 3,
msg: "hi4",
name: "test4"
}, {
id: 4,
msg: "hi5",
name: "test5"
}, {
id: 5,
msg: "hi6hi7",
name: "test6"
}, {
id: 6,
msg: "hi8",
name: "test8"
}]
I have included all messages from an user inside an array messages inside the users object.
let users = [{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "hey",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
},
{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
]
let flags = [],
output = [];
users.forEach(user => {
if (flags[user.fromUserId]) {
output.forEach(item => {
if (item.fromUserId === user.fromUserId) {
item.messages = [...item.messages, user.message]
}
})
} else {
user.messages = [user.message]
flags[user.fromUserId] = true;
output.push(user);
}
})
output will look like this:
output = [{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
"messages": ["hi", "hey", "hi"]
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
"messages": ["ola"]
}
]
Short answer:
let output = input.reduce( (acc, cur) => {
if(acc.map(item => item.fromUserId).includes(cur.fromUserId)){ //Check if the user is already included in the combined output
let found = acc.find(entry => entry.fromUserId === cur.fromUserId); //If found, combine the messages
found.message.push(cur.message);
return acc;
} else {
cur.message = [cur.message]; //the user is not included in the output yet
acc.push(cur); //so add it to the output
return acc;
}
}, []);
Full answer (Runnable code):
let input = [
{
"message": "hi",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "hey",
"fromUser": "John",
"fromUserId": "5edb1f10b82175355479f05a",
},
{
"message": "ola",
"fromUser": "Jane",
"fromUserId": "5ed9d49c7e516616600eb693",
}
];
let output = input.reduce( (acc, cur) => {
if(acc.map(item => item.fromUserId).includes(cur.fromUserId)){
let found = acc.find(entry => entry.fromUserId === cur.fromUserId);
found.message.push(cur.message);
return acc;
} else {
cur.message = [cur.message];
acc.push(cur);
return acc;
}
}, []);
console.log(output);

Check if an element is common between 2 arrays and then assign values from it

In my angular 8 application, I have 2 arrays:
array1 = [{
"SubType": "2|3|4|5|6",
},
{
"SubType": "2",
},
{
"SubType": "3|4",
},
{
"SubType": "6",
},
{
"SubType": "3|6",
},
]
&
array2 = [{
"id": 2,
"type": "1",
},
{
"id": 3,
"type": "5",
},
{
"id": 4,
"type": "4",
},
{
"id": 5,
"type": "3",
},
{
"id": 6,
"type": "2",
}
]
I am trying to check each "SubType" in array1 and see if that element(id) is present in array2 and if present assign its "type" to a variable. "SubType" is | separated which I and converting to an array using array1..split('|'). This when assigning to a variable will need to be comma separated. I tried using array filter but I am not able to find a way to loop thorough the second array. Can anyone help?
array1.forEach(reg => {
if (reg.SubType) {
let subTypeTemp = reg.SubType.split('|');
let tempVariable = subTypeTemp.some(ele => {
let stringToassign = '';
for (let i = 0; i < array2.length; i++) {
if (ele == array2[i].id) {
stringToassign += array2[i].type + ",";
}
}
})
}
})
const array1 = [
{
SubType: "2|3|4|5|6"
},
{ SubType: "2" },
{ SubType: "3|4" },
{ SubType: "6" },
{ SubType: "3|6" }
];
const array2 = [
{
id: 2,
type: "1"
},
{ id: 3, type: "5" },
{ id: 4, type: "4" },
{ id: 5, type: "3" },
{ id: 6, type: "2" }
];
const array2Obj = array2.reduce(
(acc, curr) => ({
...acc,
[curr.id]: curr.type
}),
{}
);
const types = [];
array1.forEach(item => {
const sub_types = item.SubType.split("|");
sub_types.forEach(st => {
if (st in array2Obj) {
types.push(array2Obj[st]);
}
});
});
const types_str = [...new Set(types)].join(',');
console.log("types", types_str);
You could take a Map and prevent looping array2 over and over for getting type of a wanted id.
var array1 = [{ SubType: "2|3|4|5|6" }, { SubType: "2" }, { SubType: "3|4" }, { SubType: "6" }, { SubType: "3|6" }],
array2 = [{ id: 2, type: "1" }, { id: 3, type: "5" }, { id: 4, type: "4" }, { id: 5, type: "3" }, { id: 6, type: "2" }],
types = new Map(array2.map(({ id, type }) => [id.toString(), type])),
result = array1.map(({ SubType }) => SubType
.split('|')
.map(Map.prototype.get, types)
.join()
);
console.log(result);

Retrieving value from two arrays

I have two arrays.
STUD = [{"id":1,"name":"Kida"},{"id":2,"name":"Kidb"},{"id":3,"name":"Kidc"},{"id":4,"name":"Kidd"},{"id":5,"name":"Kide"}]
IDCRD = [{"id":3,"status":"Y"},{"id":4,"status":"Y"},{"id":2,"status":"N"},{"id":5,"status":"Y"},{"id":1,"status":"N"}]
Then I have a loop:
for(var i=0;i<STUD.length;i++){
var id = STUD[i][0];
var name = STUD[i][1];
var status = ?
}
I need the status for STUD[i] from IDCRD array having the same ID inside this loop.
Have another loop on IDCRD and match ids of STUD and IDCRD then get the status
STUD = [{
"id": 1,
"name": "Kida"
}, {
"id": 2,
"name": "Kidb"
}, {
"id": 3,
"name": "Kidc"
}, {
"id": 4,
"name": "Kidd"
}, {
"id": 5,
"name": "Kide"
}];
IDCRD = [{
"id": 3,
"status": "Y"
}, {
"id": 4,
"status": "Y"
}, {
"id": 2,
"status": "N"
}, {
"id": 5,
"status": "Y"
}, {
"id": 1,
"status": "N"
}];
for (var i = 0; i < STUD.length; i++) {
var id = STUD[i].id;
var name = STUD[i].name;
for (j = 0; j < IDCRD.length; j++) {
if (STUD[i].id == IDCRD[j].id) {
var status = IDCRD[j].status;
}
}
console.log(id, name, status);
}
The function status should do what you need
var STUD = [{"id":1,"name":"Kida"},{"id":2,"name":"Kidb"},{"id":3,"name":"Kidc"},{"id":4,"name":"Kidd"},{"id":5,"name":"Kide"}];
var IDCRD = [{"id":3,"status":"Y"},{"id":4,"status":"Y"},{"id":2,"status":"N"},{"id":5,"status":"Y"},{"id":1,"status":"N"}];
function status(i){ return IDCRD.filter(w => w.id == STUD[i].id)[0].status }
console.log(status(0));
console.log(status(1));
console.log(status(2));
console.log(status(3));
console.log(status(4));
or if you run with Node you can write
status = i => IDCRD.filter(w => w.id == STUD[i].id)[0].status
You could take a Map and use id as key and take the map for an easy access to the data of IDCRD.
var stud = [{ id: 1, name: "Kida" }, { id: 2, name: "Kidb" }, { id: 3, name: "Kidc" }, { id: 4, name: "Kidd" }, { id: 5, name: "Kide" }],
IDCRD = [{ id: 3, status: "Y" }, { id: 4, status: "Y" }, { id: 2, status: "N" }, { id: 5, status: "Y" }, { id: 1, status: "N" }],
map = IDCRD.reduce((m, o) => m.set(o.id, o), new Map),
result = stud.map(o => Object.assign({}, o, map.get(o.id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Another solution could be using Array#find, but this approach iterates the array for each item to find.
var stud = [{ id: 1, name: "Kida" }, { id: 2, name: "Kidb" }, { id: 3, name: "Kidc" }, { id: 4, name: "Kidd" }, { id: 5, name: "Kide" }],
IDCRD = [{ id: 3, status: "Y" }, { id: 4, status: "Y" }, { id: 2, status: "N" }, { id: 5, status: "Y" }, { id: 1, status: "N" }],
result = stud.map(o => Object.assign({}, o, IDCRD.find(({ id }) => id === o.id)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories