I have a json response from the database like below:
"gradings": [
{
"gradingId": 1,
"enrollment": {
"enrollmentId": 1,
"rollNo": "1PC-1"
},
"grade": {
"name": "B-"
}
},
{
"gradingId": 2,
"enrollment": {
"enrollmentId": 1,
"rollNo": "1PC-1"
},
"grade": {
"name": "A+"
}
},
{
"gradingId": 3,
"enrollment": {
"enrollmentId": 2,
"rollNo": "1PC-2"
},
"grade": {
"name": "C-"
}
},
{
"gradingId": 4,
"enrollment": {
"enrollmentId": 2,
"rollNo": "1PC-2"
},
"grade": {
"name": "C-"
}
}
]
What I need is to transform above object into below structure:
I want to group grades in an array for the same enrollmentId.
"gradings": [
{
enrollmentId: 1,
rollNo: "1PC-1",
grades: [B-, A+]
},
{
enrollmentId: 2,
rollNo: "1PC-2",
grades: [C-, C-]
}
]
I didn't see any proper solution to get my requirements and I searched for lodash also.
What should I do? How can I achieve this? Thanks.
You should group grades by enrollmentId, have a array storing unique enrollments, map through that array and then complement the grades of that enrollment
Below solution (in vanilla js) could help you
const { gradings } = {
gradings: [
{
gradingId: 1,
enrollment: {
enrollmentId: 1,
rollNo: "1PC-1",
},
grade: {
name: "B-",
},
},
{
gradingId: 2,
enrollment: {
enrollmentId: 1,
rollNo: "1PC-1",
},
grade: {
name: "A+",
},
},
{
gradingId: 3,
enrollment: {
enrollmentId: 2,
rollNo: "1PC-2",
},
grade: {
name: "C-",
},
},
{
gradingId: 4,
enrollment: {
enrollmentId: 2,
rollNo: "1PC-2",
},
grade: {
name: "C-",
},
},
],
}
const enrollmentById = {}
const gradesByEnrollmentId = {}
gradings.forEach((grading) => {
if (!gradesByEnrollmentId[grading.enrollment.enrollmentId]) {
gradesByEnrollmentId[grading.enrollment.enrollmentId] = [grading.grade.name]
} else {
gradesByEnrollmentId[grading.enrollment.enrollmentId].push(grading.grade.name)
}
if (!enrollmentById[grading.enrollment.enrollmentId]) {
enrollmentById[grading.enrollment.enrollmentId] = { ...grading.enrollment }
}
})
const res = {
gradings: Object.values(enrollmentById).map((enrollment) => ({
...enrollment,
grades: gradesByEnrollmentId[enrollment.enrollmentId],
})),
}
console.log(res)
Related
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))
I want to map from this:
companies: {
apples: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
peaches: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
};
to this:
{ "companies": {
"apples": [
{
"name": "Q7",
"price": 1
},{
"name": "Q6",
"price": 1
}
],
"peaches": [
{
"name": "Q7",
"price": 1
},{
"name": "Q6",
"price": 1
}
]
}
}
How I am trying to achieve this:
I have a selector which gives me the companies object and then I map over it and assemble my object but I don't get it quite right.
This is my function:
const weaponProducts = Object.entries(getCompanies(state)).map(([companyType, companies]) => {
const prod = Object.entries(companies).map(([key, companies]) => {
return {
name: key,
price: companies.price
}
});
return {
[companyType]: prod
};
});
getCompanies(state) returns the following object:
{
"companies": {
"apples": {
"Q7": {
"price": 1
},
"Q6": {
"price": 1
}
},
"peaches": {
"Q7": {
"price": 1
},
"Q6": {
"price": 1
}
}
}
}
The result of the function is the following. But as explained I want it to look like the second code section of my post.
[
{
"apples": [
{
"name": "Q7",
"price": 1
},
{
"name": "Q6",
"price": 1
},
]
},
{
"peaches": [
{
"name": "Q7",
"price": 1
},
{
"name": "Q6",
"price": 1
},
]
}
]
since your desired output is an object, not an array, you should use reduce instead of map:
let companies = {
apples: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
peaches: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
}
let fruit = Object.keys(companies)
let output = fruit.reduce((output, currentFruit) => {
output[currentFruit] = Object.keys(companies[currentFruit]).map(q => {
return { name: q, price: companies[currentFruit][q].price }
})
return output
}, {});
console.log(output);
(I think there was a syntax error in your companies object, I corrected in the snippet)
You can also take entries and then map the objects accordingly.
var companies = { apples: { Q7: { price: 1, }, Q6: { price: 1, }, }, peaches: { Q7: { price: 1, }, Q6: { price: 1, } }};
const result = (inputObj) =>
Object.fromEntries(
Object.entries(inputObj).map(([key, obj]) => [
key,
Object.entries(obj).map(([name, val]) => ({ name, ...val })),
])
);
console.log(result(companies));
If you're down to try something new, here's a different way to express the desired transformation using a library I authored.
const x = { companies: { apples: { Q7: { price: 1, }, Q6: { price: 1, }, }, peaches: { Q7: { price: 1, }, Q6: { price: 1, }, }, } }
const { pipe, fork, map, tap, get } = rubico
const y = map(map(pipe([
Object.entries,
map(fork({
name: get(0),
price: get([1, 'price']),
})),
])))(x)
console.log(JSON.stringify(y, null, 2))
<script src="https://unpkg.com/rubico/index.js"></script>
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);
I am trying to transform complex JavaScript object. Below is my code. As you can see, it's a lot of code. I am looking for a better/common way to achieve the same result. Maybe ES6 map/Reduce? (I am not allow to do import/require)
function test() {
var input = {
number: 555,
obj1: {
fld1: "11",
persons: [
{
name: "smith",
phone: "222-222-2222"
}
],
},
obj2: {
obj3: {
day: "2019-02-04"
}
},
myArr: [
{
number: 444,
qty: 20,
unit: "ton",
item: {
item_id: 1,
description: "item 1"
}
},
{
number: 111,
qty: 15,
unit: "pieces",
item: {
item_id: 2,
description: "item 2"
}
}
]
}
var result = {
id: input.number,
object1: {
id: input.obj1.number,
contacts: getArr2(input)
},
object2: {
date: input.obj2.obj3.day,
},
list: getArr1(input),
}
return result; // echo back the input received
}
console.log(JSON.stringify(test()));
function getArr1(input) {
var arr = [];
input.myArr.forEach(function (prod) {
let p = {
id: prod.number,
itemId: prod.item.item_id,
description: prod.item.description,
quantity: {
value: prod.qty,
uom: prod.unit
}
}
arr.push(p);
});
return arr;
}
function getArr2(input) {
var arr = [];
input.obj1.persons.forEach(function (person) {
let p = {
name: person.name,
cell: person.phone
}
arr.push(p);
});
return arr;
}
And the result is
{
"id": 555,
"object1": {
"contacts": [{
"name": "smith",
"cell": "222-222-2222"
}]
},
"object2": {
"date": "2019-02-04"
},
"list": [{
"id": 444,
"itemId": 1,
"description": "item 1",
"quantity": {
"value": 20,
"uom": "ton"
}
}, {
"id": 111,
"itemId": 2,
"description": "item 2",
"quantity": {
"value": 15,
"uom": "pieces"
}
}]
}
You could use the power of destructuring and renaming.
function getProds(products) {
return products.map(({ number: id, qty: value, unit: uom, item: { item_id: itemId, description } }) =>
({ id, itemId, description, quantity: { value, uom } }));
}
function getPersons(persons) {
return persons.map(({ name, phone: cell }) => ({ name, cell }));
}
function convert({ number: id, obj1, obj2: { obj3: { day: date } }, myArr }) {
return {
id,
object1: {
id: obj1.number,
contacts: getPersons(obj1.persons)
},
object2: { date },
list: getProds(myArr)
};
}
var data = { number: 555, obj1: { fld1: "11", persons: [{ name: "smith", phone: "222-222-2222" }], }, obj2: { obj3: { day: "2019-02-04" } }, myArr: [{ number: 444, qty: 20, unit: "ton", item: { item_id: 1, description: "item 1" } }, { number: 111, qty: 15, unit: "pieces", item: { item_id: 2, description: "item 2" } }] };
console.log(convert(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're on the right track with map/reduce.
Here's an example (getArr1 would be similar):
function getArr2(input) {
// Don't need map if new object is identical
// Could also do the mapping within the reduce callback
return input.obj1.persons
.map(person => ({ name: person.name, cell: person.phone }))
.reduce((accumulator, currentValue) => {
accumulator.push(currentValue);
return accumulator;
}, []);
}
There's another example in the documentation at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Remove_duplicate_items_in_array
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; }