How to create a new object from array of objects? - javascript

I have the following dynamic array of objects:
[
{
id: "1"
name: "Jane"
age: 25
},
{
id: "2"
name: "John"
age: 35
},
{
id: "3"
name: "James"
age: 27
},
]
I need to create new object like this:
"peopleSelected:{
"1":
{
"name": "Jane",
"age": 25
},
"2":
{
"name": "John",
"age": 35
},
"3":
{
"name": "James",
"age": 27
},
where structure is
"id" :
{
"name":name,
"age":"age
}
and I need to save this newly created object using useState, I can't figure out how to do that. Please help.

Using Array.prototype.reduce()
const arr = [
{
id: "1",
name: "Jane",
age: 25,
},
{
id: "2",
name: "John",
age: 35,
},
{
id: "3",
name: "James",
age: 27,
},
],
solution = {
peopleSelected: arr.reduce((acc, { id, name, age }) => {
acc[id] = { name, age };
return acc;
}, {}),
};
console.log(solution);

You can use object destructuring as below:
import React from 'react';
import { useState, useEffect } from 'react';
let people = [
{
id: "1",
name: "Jane",
age: 25
},
{
id: "2",
name: "John",
age: 35
},
{
id: "3",
name: "James",
age: 27
}
];
function App() {
const [ selectedPeople, setSelectedPeople ] = useState({});
useEffect(() => {
console.log(Object.entries(people));
let extractedArray = Object.entries(people);
let result = extractedArray.map((item) => {
return `${item[1].id}: ${{
"name": item[1].name,
"age": item[1].age
}}`
})
console.log(result);
// Performing object destructuring and setting the state of selectedPeople as an object
setSelectedPeople({...people})
}, [])
return <div>
<pre>
{JSON.stringify(selectedPeople, null, '\t')}
</pre>
</div>;
}
export default App;

Related

Create an array of object by mapping and joining two array of objects

I have an array of objects like this
const data = [{
"id": 1,
"content": {
"type": "img",
"state": "rejected"
},
"entity": {
"type": "student",
"studentID": [
44
]
},
"status": "rejected"
},
{
"id": 2,
"content": {
"type": "img",
"state": "approved"
},
"entity": {
"type": "student",
"studentID": [
45
]
},
"status": "approved"
},
{
"id": 3,
"content": {
"type": "img",
"state": "approved"
},
"entity": {
"type": "student",
"studentID": [
44
]
},
"status": "approved"
}
]
As you can see, we have 2 objects of student id 44 (one with status rejected and one with approved) and one of student id 45.
I have another array of object with student info like this
const students = [{
student_id: 44,
fname: 'student 1',
lname: '.',
school: 'XYZ',
},
{
student_id: 45,
fname: 'student 2',
lname: '.',
school: 'ABC',
}
]
Now, i want to create a new array of object with both of them mapped, but each object in data mapped with their corresponding student (relation between entity.studentID[0] in data with student_id in students, so that the resultant array of object is
[{
student_id: 44,
fname: 'student 1',
lname: '.',
school: 'XYZ',
item: {
id: 1,
status: "rejected"
},
},
{
student_id: 45,
fname: 'student 2',
lname: '.',
school: 'ABC',
item: {
id: 2,
status: "approved"
},
},
{
student_id: 44,
fname: 'student 1',
lname: '.',
school: 'XYZ',
item: {
id: 3,
status: "approved"
},
},
]
What i did was i ran a loop on students and tried using map but that returns me an array of objects that qualify the condition instead of the objects themselves.
let arr = []
for (let student of students) {
let obj = { ...student
};
obj["item"] = data.map((p) => {
if (p.entity.studentId[0] === student.student_id) {
return {
id: p.id,
status: p.status,
};
}
});
arr.push(obj);
}
Where am i going wrong and what should i do instead?
Your code is a bit complex,below is a more simple solution for you
let result = data.map(d =>{
let stu = students.find(i => d.entity.studentID.includes(i.student_id))
return {...stu,item:{id:d.id,status:d.status}}
})
console.log(result)
For your code,the reason is that map will return undefined if it not meets p.entity.studentId[0] === student.student_id
let arr = []
for (let student of students) {
let obj = { ...student
};
obj["item"] = data.map((p) => {
if (p.entity.studentId[0] === student.student_id) {
return {
id: p.id,
status: p.status,
};
}
// will return undefined when not meet the if condition
});
arr.push(obj);
}
Working code
const data = [{
"id": 1,
"content": {
"type": "img",
"state": "rejected"
},
"entity": {
"type": "student",
"studentID": [
44
]
},
"status": "rejected"
},
{
"id": 2,
"content": {
"type": "img",
"state": "approved"
},
"entity": {
"type": "student",
"studentID": [
45
]
},
"status": "approved"
},
{
"id": 3,
"content": {
"type": "img",
"state": "approved"
},
"entity": {
"type": "student",
"studentID": [
44
]
},
"status": "approved"
}
]
const students = [{
student_id: 44,
fname: 'student 1',
lname: '.',
school: 'XYZ',
},
{
student_id: 45,
fname: 'student 2',
lname: '.',
school: 'ABC',
}
]
let result = data.map(d => {
let stu = students.find(i => d.entity.studentID.includes(i.student_id))
return { ...stu, item:{ id:d.id, status:d.status }}
})
console.log(result)
Try this if it's working:
let newStudent = [];
data.map((data) => {
const studentId = data['entity']['studentID'];
function sts() { return data.status};
students.map((student) => {
const std_id = student.student_id;
if (std_id == studentId) {
newStudent.push({
student_id: std_id,
fname: student.fname,
lname: student.lname,
school: student.school,
id: newStudent.length + 1,
status: sts()
});
}
})
})

Grouping array of objects to object of arrays by multiple keys and adding the id's of the group to the key

Made sample of code -
Interface -
interface IInterface {
id: number;
name: string;
age: number;
}
array -
const arr: IInterface[] = [
{
id: 1,
name: 'daniel',
age: 12
},
{
id: 2,
name: 'jonny',
age: 13
},
{
id: 3,
name: 'daniel',
age: 12
},
{
id: 4,
name: 'daniel',
age: 12
}
]
GroupBy function -
const GroupBy = (
array: IInterface[],
f: (element: IInterface) => (string | number | undefined)[]
) => {
const groups: { [key: string]: IInterface[] } = {};
array.forEach((object) => {
const group = f(object).join("-");
groups[group] = groups[group] || [];
groups[group].push(object);
});
return groups;
};
Using the groupBy function -
const Grouped = GroupBy(arr, (element: IInterface) => {
return [
element.name, element.age,
];
});
Result now -
{
"daniel-12": [
{
"id": 1,
"name": "daniel",
"age": 12
},
{
"id": 3,
"name": "daniel",
"age": 12
},
{
"id": 4,
"name": "daniel",
"age": 12
}
],
"jonny-13": [
{
"id": 2,
"name": "jonny",
"age": 13
}
]
}
Wanted result -
{
"daniel-12-ids-1-3-4": [
{
"id": 1,
"name": "daniel",
"age": 12
},
{
"id": 3,
"name": "daniel",
"age": 12
},
{
"id": 4,
"name": "daniel",
"age": 12
}
],
"jonny-13-ids-2": [
{
"id": 2,
"name": "jonny",
"age": 13
}
]
}
Need that all the group id's will by at the key name
.......................................................................................................................................................
You could create a new object from the old one.
const
grouped = { "daniel-12": [{ id: 1, name: "daniel", age: 12 }, { id: 3, name: "daniel", age: 12 }, { id: 4, name: "daniel", age: 12 }], "jonny-13": [{ id: 2, name: "jonny", age: 13 }] },
result = Object.fromEntries(Object.entries(grouped).map(([k, v]) => [
[k, 'ids', v.map(({ id }) => id).join('-')].join('-'),
v
]));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Nested filter returning empty array

Below is the data that I am receiving and I am trying to filter so that a new array contains only objects with the desired location.
However, I'm running into an issue where my function is returning [], an empty array.
data:
[
{ data: [[Object], [Object], [Object]], id: 1 },
{ data: [[Object]], id: 2 },
{ data: [[Object], [Object], [Object], [Object]], id: 3 }
];
data[1]:
{"data": [{"name": "Joe", "job": "N/A", "location": "Los Angeles"}], "id": 2}
This is my current function:
const locations = ["Los Angeles", "Chicago"];
...
const filteredData = data.filter((i) =>
i.data.filter((j) => locations.includes(j.location)),
);
return filteredData;
What is wrong and how can I fix this and get it filtering correctly?
In the callback you pass to the Array.filter(), you need to return a boolean value to filter the array. If you do not return anything, the filter returns an empty array.
But in your case, you are returning inner filtered array that returns at least an empty array and the outer filter behaves it as a true value. So the outer filter will return all of the items in the original array. (not an empty one as you stated)
Also you are returning filteredData in a place where it results in a syntax error.
const data = [
{"data": [{"name": "Joe", "job": "N/A", "location": "Los Angeles"}], "id": 2},
{"data": [{"name": "Jane", "job": "N/A", "location": "Charlotte"}], "id": 3},
]
const locations = ["Los Angeles", "Chicago"];
const filteredData = data.filter((i) =>
i.data.filter((j) => locations.includes(j.location)).length > 0,
);
console.log(filteredData);
Another Option is use some() to get your expected result. This way you don't need to loop through all item in data array comparing to filter()
const data = [
{ data: [{ name: "Joe", job: "N/A", location: "Los Angeles" }], id: 2 },
{ data: [{ name: "Jane", job: "N/A", location: "Charlotte" }], id: 3 },
{ data: [{ name: "Sam", job: "N/A", location: "SSS" }], id: 4 },
{
data: [
{ name: "John", job: "N/A", location: "AAA" },
{ name: "Doe", job: "N/A", location: "BBB" },
],
id: 5,
},
];
const locations = ["Los Angeles", "Chicago", "AAA"];
const existData = data.filter(el =>
el.data.some(item => locations.includes(item.location))
);
console.log(existData);
If you also want to filter the data array, you can do like below.
const data = [
{ data: [{ name: "Joe", job: "N/A", location: "Los Angeles" }], id: 2 },
{ data: [{ name: "Jane", job: "N/A", location: "Charlotte" }], id: 3 },
{ data: [{ name: "Sam", job: "N/A", location: "SSS" }], id: 4 },
{
data: [
{ name: "John", job: "N/A", location: "AAA" },
{ name: "Doe", job: "N/A", location: "BBB" },
],
id: 5,
},
];
const locations = ["Los Angeles", "Chicago", "AAA"];
const filteredData = data.reduce((acc, cur) => {
const filteredItem = cur.data.filter(item => locations.includes(item.location));
if (filteredItem.length) {
acc.push({ ...cur, data: filteredItem });
}
return acc;
}, []);
console.log(filteredData);

Flatten array with multiple objects with nested objects

this particular desired outcome I'm trying to do is turning out to be a bit more challenging that I had expected for someone who is just starting out programming.
I'm storing the results of an API query in an array variable that looks like this:
[{
balance: 4444,
playerInfo: {
age: "18",
gender: "Male",
level: "2",
name: "Joe"
}
}, {
balance: 3333,
playerInfo: {
age: "45",
gender: "Male",
level: "3",
name: "Angel"
}
}, {
balance: 2222,
playerInfo: {
age: "20",
gender: "Female",
level: "11",
name: "Luce"
}
}]
My desired outcome is:
[{
balance: 4444,
level: "2",
name: "Joe"
}, {
balance: 3333,
level: "3",
name: "Angel"
}, {
balance: 2222,
level: "11",
name: "Luce"
}]
I've had some minor progress with flat and flatMap but not entirely sure if its the right way to go for compatibility since the intended target group may be using outdated browsers.
The logic for some other answers are a bit tough for me to grasp atm so would appreciate a few pointers in case
Thank you!
You can make use of Array.map and Object destructuring.
let data = [{balance:4444,playerInfo:{age:"18",gender:"Male",level:"2",name:"Joe"}},{balance:3333,playerInfo:{age:"45",gender:"Male",level:"3",name:"Angel"}},{balance:2222,playerInfo:{age:"20",gender:"Female",level:"11",name:"Luce"}}]
const formatData = (data) => {
return data.map(({balance, playerInfo}) => ({
balance,
level: playerInfo.level,
name: playerInfo.name
}))
}
console.log(formatData(data))
let data = [{balance:4444,playerInfo:{age:"18",gender:"Male",level:"2",name:"Joe"}},{balance:3333,playerInfo:{age:"45",gender:"Male",level:"3",name:"Angel"}},{balance:2222,playerInfo:{age:"20",gender:"Female",level:"11",name:"Luce"}}]
const formatData = (data) => {
return data.map(({ balance, playerInfo: { level, name }}) => ({
balance,
level,
name
}))
}
console.log(formatData(data));
You can directly use map method to transform.
let input = [{
balance: 4444,
playerInfo: {
age: "18",
gender: "Male",
level: "2",
name: "Joe"
}
}, {
balance: 3333,
playerInfo: {
age: "45",
gender: "Male",
level: "3",
name: "Angel"
}
}, {
balance: 2222,
playerInfo: {
age: "20",
gender: "Female",
level: "11",
name: "Luce"
}
}];
let output = input.map(obj => ({
balance: obj.balance,
level: obj.playerInfo?.level,
name: obj.playerInfo?.name,
}));
console.log(output);
Something short 'n sweet is this:
let rawData = [{
balance: 4444,
playerInfo: {
age: "18",
gender: "Male",
level: "2",
name: "Joe"
}
}, {
balance: 3333,
playerInfo: {
age: "45",
gender: "Male",
level: "3",
name: "Angel"
}
}, {
balance: 2222,
playerInfo: {
age: "20",
gender: "Female",
level: "11",
name: "Luce"
}
}]
let formattedData =
rawData.map(({
balance,
playerInfo: {
level,
name
}
}) => ({ balance, level, name }))
console.log(formattedData)

Filter a list based on a selection

Given the data below, I have two select lists, the first select list is to display the name of each person... the second select list is two display the name of the children of the selected person. Using lodash what is the easiest way to do this?
const people = [{
id: "1",
name: "bob",
gender: "male",
children: [{
id: "1",
name: "sarah"
}]
},
{
id: "2",
name: "tom",
gender: "male",
children: [{
id: "1",
name: "lisa"
}]
},
{
id: "3",
name: "sue",
gender: "female",
children: [{
id: "1",
name: "larry"
}]
}
]
Please find the solution as below:
import map from "lodash/map";
import partialRight from "lodash/partialRight";
import pick from "lodash/pick";
import find from "lodash/find";
const test = [
{
id: "2",
name: "tom",
gender: "male",
children: [
{
id: "1",
name: "lisa"
}
]
},
{
id: "3",
name: "sue",
gender: "female",
children: [
{
id: "1",
name: "larry"
}
]
}
];
// Person selection list
const persons = map(test, partialRight(pick, ["id", "name", "gender"]));
// Replace selected person value in `persons[0]`.
const childrens = find(test, item => item.id === persons[0].id).children;

Categories