How to group some properties of objects based on other property - javascript

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

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))

Extracting objects out of arrays

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>

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);

JavaScript ES6 better way to transform complex object

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

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