add another field to jason array through looping in javascript - javascript

I have added Computer Marks Manually But I have to add ComputerMarks Field through looping to use the given JSON Array which is AnotherSubject To Match The Student Name with JASON Array then Add ComputerMarks field to each student JASON File
let Student1={
Name:"Mark",
MathMarks:80,
EnglishMarks:75,
ScienceMarks:63,
}
let Student2={
Name:"Bob",
MathMarks:90,
EnglishMarks:81,
ScienceMarks:88,
}
let Student3={
Name:"Julia",
MathMarks:88,
EnglishMarks:87,
ScienceMarks:89,
}
let Student4={
Name:"Anthony",
MathMarks:60,
EnglishMarks:64,
ScienceMarks:61,
}
let AnotherSubject=[
{name:'Mark', ComputersMarks:90},
{name:'Anthony', ComputersMarks:70},
{name:'Julia', ComputersMarks:88},
{name:'Bob', ComputersMarks:81}]
StudentsArray=[Student1,Student2,Student3,Student4]
let StudentMarks={
students:StudentsArray
}
Student1.ComputersMarks=90
Student2.ComputersMarks=81
Student3.ComputersMarks=88
Student4.ComputersMarks=70
console.log(StudentMarks.students)

a possible way
const
Student1 = { Name: 'Mark', MathMarks: 80, EnglishMarks: 75, ScienceMarks: 63 }
, Student2 = { Name: 'Bob', MathMarks: 90, EnglishMarks: 81, ScienceMarks: 88 }
, Student3 = { Name: 'Julia', MathMarks: 88, EnglishMarks: 87, ScienceMarks: 89 }
, Student4 = { Name: 'Anthony', MathMarks: 60, EnglishMarks: 64, ScienceMarks: 61 }
, StudentsList = [ Student1, Student2, Student3, Student4 ]
, AnotherSubject =
[ { Name: 'Mark', ComputersMarks: 90 }
, { Name: 'Anthony', ComputersMarks: 70 }
, { Name: 'Julia', ComputersMarks: 88 }
, { Name: 'Bob', ComputersMarks: 81 }
]
function addNewProp ( List, newRefs )
{
let [key,prop] = Object.keys( newRefs[0])
List.forEach(el =>
{
let newP = newRefs.find(x=>x[key]===el[key] )
if (newP) el[prop] = newP[prop]
});
}
addNewProp(StudentsList, AnotherSubject)
console.log('Student1 ->', JSON.stringify( Student1) )
console.log('Student2 ->', JSON.stringify( Student2) )
console.log('Student3 ->', JSON.stringify( Student3) )
console.log('Student4 ->', JSON.stringify( Student4) )
.as-console-wrapper {max-height: 100%!important;top:0}

One easy way to do this would be to use the power of reduce and map.
Reduce basically makes an Object from an Array and Map transforms each item of an array and return the new array.
Additionally, we use the spear syntax ... to manipulate objects.
// Here we are converting [{name: '', marks: 1 }] into { name: marks }
const AnotherSubjectsMap = AnotherSubject.reduce((accu, curr) => ({
...accu,
[curr.name]: curr.ComputersMarks
}), {});
let StudentsArray = [Student1, Student2, Student3, Student4]
// Here were are going through the array and adding an extra parameter
StudentsArray = StudentsArray.map(Student => ({
...Student, // This line means we are copying all keys of Student as it is
ComputersMarks: AnotherSubjectsMap[Student.Name]
}));
let StudentMarks = {
students: StudentsArray
}
console.log(StudentMarks.students)
let Student1 = {
Name: "Mark",
MathMarks: 80,
EnglishMarks: 75,
ScienceMarks: 63,
}
let Student2 = {
Name: "Bob",
MathMarks: 90,
EnglishMarks: 81,
ScienceMarks: 88,
}
let Student3 = {
Name: "Julia",
MathMarks: 88,
EnglishMarks: 87,
ScienceMarks: 89,
}
let Student4 = {
Name: "Anthony",
MathMarks: 60,
EnglishMarks: 64,
ScienceMarks: 61,
}
let AnotherSubject = [{
name: 'Mark',
ComputersMarks: 90
},
{
name: 'Anthony',
ComputersMarks: 70
},
{
name: 'Julia',
ComputersMarks: 88
},
{
name: 'Bob',
ComputersMarks: 81
}
]
AnotherSubjectsMap = AnotherSubject.reduce((accu, curr) => ({
...accu,
[curr.name]: curr.ComputersMarks
}), {});
StudentsArray = [Student1, Student2, Student3, Student4]
StudentsArray = StudentsArray.map(Student => ({
...Student,
ComputersMarks: AnotherSubjectsMap[Student.Name]
}));
let StudentMarks = {
students: StudentsArray
}
console.log(StudentMarks.students)

Related

how to find min value from array of objects over multiple keys in single function

I have to find min value from an array of objects but I have multiple keys and I want to find the min value of all keys or specified keys.
For example
var users = [
{id:"1", name:"ABC", age:30, height: 75, weight: 83},
{id:"1", name:"ABC", age:24, height: 63, weight: 75},
{id:"1", name:"ABC", age:27, height: 56, weight: 55}
]
In this example, I want to find the users with min age, height and weight.
But by using a single function.
I am using this function. its finds min age only.
findMin(data) {
return data.reduce((min, u) => u.age < min ? u.age : min, data[0].age);
},
You can try this :
const users = [ {id:"1", name:"ABC", age:30, height: 75, weight: 83}, {id:"1", name:"ABC", age:24, height: 63, weight: 75}, {id:"1", name:"ABC", age:27, height: 56, weight: 55} ];
const min = (arr, key) => arr.reduce((min, el) => el[key] < min[key] ? el : min);
const keys = ['age', 'height', 'weight'];
const result = Object.fromEntries(keys.map(k => [k, min(users, k)]));
console.log(result)
Using only 1 function :
const users = [ {id:"1", name:"ABC", age:30, height: 75, weight: 83}, {id:"1", name:"ABC", age:24, height: 63, weight: 75}, {id:"1", name:"ABC", age:27, height: 56, weight: 55} ];
const min = (arr, keys) => arr.reduce(
(min, el) => Object.fromEntries(keys.map(k => [k, el[k] < min[k][k] ? el : min[k]])),
{age: arr[0], height: arr[0], weight: arr[0]}
);
const result = min(users, ['age', 'height', 'weight']);
console.log(result)
Output :
{
age: { minAgeItem },
weight: { minWeightItem },
height: { minHeightItem }
}
This is my modified version!
const arr = [{
id: "1",
name: "ABC",
age: 30,
height: 75,
weight: 83
},
{
id: "1",
name: "ABC",
age: 24,
height: 63,
weight: 75
},
{
id: "1",
name: "ABC",
age: 27,
height: 56,
weight: 55
}
];
function getMins(array) {
let minAge = Infinity,
minHeight = Infinity,
minWeight = Infinity;
const output = [{}, {}, {}];
array.forEach((user) => {
if (user.age <= minAge) {
minAge = user.age;
output[0] = user;
}
if (user.height <= minHeight) {
minHeight = user.height;
output[1] = user;
}
if (user.weight <= minWeight) {
minWeight = user.weight;
output[2] = user;
}
});
return output;
}
console.log(getMins(arr));
I hope I understand you well, that you want to extract min value for each of fields. Then you could expand your functions to return an object like this:
Note: open chrome console and check output, SO console is giving some weird results!
var users = [
{id:"1", name:"ABC", age:30, height: 75, weight: 83},
{id:"1", name:"ABC", age:24, height: 63, weight: 75},
{id:"1", name:"ABC", age:27, height: 56, weight: 55}
]
function findMin(data) {
return data.reduce((mins, u) => {
mins['minAge'] = (u.age < mins['minAge'] ? u.age : mins['minAge']);
mins['minHeight'] = (u.height < mins['minHeight'] ? u.height : mins['minHeight']);
mins['minWeight'] = (u.weight < mins['minWeight'] ? u.weight : mins['minWeight']);
return mins
}, {
minAge: data[0].age,
minHeight: data[0].height,
minWeight: data[0].weight
});
}
console.log(findMin(users))
edit:
Added more flexibility to the function:
var users = [
{ id: "1", name: "ABC", age: 30, height: 75, weight: 83 },
{ id: "1", name: "ABC", age: 24, height: 63, weight: 75 },
{ id: "1", name: "ABC", age: 27, height: 56, weight: 55 }
];
function findMin(data, keys) {
return data.reduce((mins, u) => {
keys.forEach(
(key) => (mins[key] = u[key] < mins[key] ? u[key] : mins[key])
);
return mins;
}, keys.reduce((accumulator, value) => {
return {...accumulator, [value]: data[0][value]};
}, {}));
}
console.log(findMin(users, ['age','height']));
Another one approach
const users = [
{id:"1", name:"ABC", age:30, height: 75, weight: 83},
{id:"2", name:"ABC", age:24, height: 63, weight: 75},
{id:"3", name:"ABC", age:27, height: 56, weight: 55},
];
const getMinsBy = (users, properties) => {
const minBy = (prop) => users.reduce((min, curr) => (min[prop] > curr[prop]) ? curr : min)
return properties.reduce((acc, prop) => ({ ...acc, [prop]: minBy(prop) }), {});
};
console.log(getMinsBy(users, ['age', 'height', 'weight']));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Using the below statement you can sort the array based on age, height and weight:
objs.sort((a,b)=> (a.age - b.age || a.height - b.height || a.weight -
b.weight));
Using the above logic, you can append how many ever sort columns you might need in the order you need them.
The above statement is same as below SQL query:
SELECT * FROM OBJS ORDER BY NAME,AGE,ROLLNO;
I would also suggest to sort this at backend only instead of frontend as to reduce complexity at frontend.

compare Two array and result only the values

I need to filter an array of objects
const arrayOne = [
{id: 33, name: "fruit"},
{id: 157, name: "car"},
{id: 193, name: "water"},
];
const arrayTwo = [33, 193];
I need only the names in an array (without the key)
Expected output
["fruit", "water"]
1) You can easily achive the result using Map
const arrayOne = [
{ id: 33, name: "fruit" },
{ id: 157, name: "car" },
{ id: 193, name: "water" },
];
const map = new Map();
arrayOne.forEach((o) => map.set(o.id, o.name));
const arrayTwo = [33, 193];
const result = arrayTwo.map((o) => map.get(o));
console.log(result);
2) You can also achieve the result using map and find
const arrayOne = [
{ id: 33, name: "fruit" },
{ id: 157, name: "car" },
{ id: 193, name: "water" },
];
const arrayTwo = [33, 193];
const result = arrayTwo.map((id) => arrayOne.find((o) => o.id === id)?.name);
console.log(result);
you can just simply do
const arrayOne = [
{ id: 33, name: "fruit" },
{ id: 157, name: "car" },
{ id: 193, name: "water" }
];
const arrayTwo = [33, 193];
let keepResult = [];
arrayOne.map((a1) => {
arrayTwo.map((a2) => {
if (a1.id === a2) {
keepResult.push(a1.name);
}
});
});
console.log("result show", keepResult);
const arrayOne = [
{id: 33, name: "fruit"},
{id: 157, name: "car"},
{id: 193, name: "water"},
];
const arrayTwo = [33, 193];
let newArray = arrayOne.filter(item => arrayTwo.includes(item.id)).map(item => item.name)
console.log(newArray);
try this
this function is your solution:
const findNames = () => {
let names = []
arrayOne.forEach(item => {
if (arrayTwo.includes(item.id)) {
names = [...names, item.name]
}
})
return names
}
Here is your compare() function for getting array of names based on two array
const arrayOne = [
{id: 33, name: "fruit"},
{id: 157, name: "car"},
{id: 193, name: "water"},
];
const arrayTwo = [33, 157];
function compare(arrayOne, arrayTwo) {
let result = [];
arrayOne.filter(element => arrayTwo.indexOf(element.id) !== -1 ).forEach(element => { result.push(element.name) });
return result ;
}
Use a flatmap on the first array and include only those members having an id property included in array two.
arrayOne.flatMap(({ id, name }) => arrayTwo.includes(id) ? [name]: []);
const arrayOne = [
{id: 33, name: "fruit"},
{id: 157, name: "car"},
{id: 193, name: "water"},
];
const arrayTwo = [33, 193];
const result = arrayOne.flatMap(({ id, name }) => arrayTwo.includes(id) ? [name]: []);
console.log(result);

How to join 2 arrays into an array of objects

I've got some headers and peopleData:
const headers = ["name", "age", "nationality"]
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
]
I want to combine both and return an array of objects looking like:
[{
name: "John",
age: 31,
nationality: "Spanish"
}, {
name: "Jane",
age: 41,
nationality: "Italian"
}, {
name: "Johnson",
age: 11,
nationalityL: "Thai"
}, {
name: "Rob",
age: 13,
nationality: "Japanese"
}]
So far I came up to this:
const people = peopleData.map((person, i) => {
return headers.map((header, index) => {
return {
[header]: person[index]
}
})
})
This solution does not work since it creates nested objects:
[[{
name: "John"
}, {
age: 31
}, {
nationality: "Spanish"
}], [{
name: "Jane"
}, {
age: 41
}, {
nationality: "Italian"
}], [{
name: "Johnson"
}, {
age: 11
}, {
nationality: "Thai"
}], [{
name: "Rob"
}, {
age: 13
}, {
nationality: "Japanese"
}]]
Example below:
Credit to Andreas comment, better performant below
const headers = ["name", "age", "nationality"];
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
];
const o = peopleData.map(a =>
a.reduce((acc, b, i) => {
acc[headers[i]] = b;
return acc;
}, {})
);
console.log(o);
In one line-er, but less performent
const headers = ["name", "age", "nationality"];
const peopleData = [
["John", 31, "Spanish"],
["Jane", 41, "Italian"],
["Johnson", 11, "Thai"],
["Rob", 13, "Japanese"],
];
const o = peopleData.map(a =>
a.reduce((acc, b, i) => ({ ...acc, [headers[i]]: b }), {})
);
console.log(o);
You can wrap your inner .map() in a call to Object.fromEntries() which will build an object for you - it takes an array of [[key, value],...] pairs, and so you can change your inner map to return a [key, value] pair array instead of objects like so:
const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];
const res = peopleData.map(person => Object.fromEntries(person.map(
(val, i) => [headers[i], val]
)));
console.log(res);
Or, you can stick with your approach of returning an array of objects, but then merge the objects within the array together using Object.assign() and the spread syntax ...:
const headers = ["name", "age", "nationality"];
const peopleData = [ ["John", 31, "Spanish"], ["Jane", 41, "Italian"], ["Johnson", 11, "Thai"], ["Rob", 13, "Japanese"], ];
const res = peopleData.map(person => Object.assign(...person.map(
(val, i) => ({[headers[i]]: val})
)));
console.log(res);
A simply solution easy to understand! Iterate all peopleData and put them in a new object using the array headers:
const headers = ["name", "age", "nationality"];
const peopleData = [["John", 31, "Spanish"],["Jane", 41, "Italian"],["Johnson", 11, "Thai"],["Rob", 13, "Japanese"]];
let result = [];
peopleData.forEach((e, i) => { //iterate data
result[i] = {};
result[i][headers[0]] = e[0];
result[i][headers[1]] = e[1];
result[i][headers[2]] = e[2];
});
console.log(result);

Filter javascript object of arrays for all keys

I am new to javascript. lets say I have the following object of arrays
const object1 = {
name: ['David', 'Juan', 'Simon', 'Lukas'],
age: [41, 22, 33, 50],
salary: [100, 80, 120, 150]
};
I would like to create a new object which filter the data of people older than a value (e.g. 30). I was loooking to filter, Object.fromEntries, Object.entries but I couldnt find a possible solution.
The result should be
NewObject {
name: Array['David', 'Simon', 'Lukas'],
age: Array[41, 33, 50],
salary: Array[100, 120, 150]
};
Thanks for any suggestions
Convert your current structure to a more convenient data structure(JSON) like this:
const workers = [
{
name : 'David',
age : 41,
salary : 100
},
{
name : 'Juan',
age : 22,
salary : 80
},
{
name : 'Simon',
age : 33,
salary : 120
},
{
name : 'Lukas',
age : 50,
salary : 150
}
];
const olderThan30 = workers.filter(worker => worker.age > 30);
console.log(olderThan30);
// This console log will return this, an array of JSON objects that match the criteria of the filter function.
// [
// { name : "David", age : 41, salary : 100 },
// { name : "Simon", age : 33, salary : 120 },
// { name : "Lukas", age : 50, salary : 150 }
// ]
I hope this will help.
Like #CharlieFish mentioned, your data structure is not the normal way of doing things, which is where you'd do this instead:
const employees = [
{ name: 'David', age: 41, salary: 100 },
{ name: 'Simon', age: 33, salary: 120 },
{ name: 'Lukas', age: 50, salary: 150 },
];
const over30 = employees.filter(employee => employee.age > 30);
If you did need to stick with your pattern instead, you can still do it, but you'd have to filter each individual array:
const isOver30 = (_, i) => object1.age[i] > 30;
const thoseOver30 = {
name: object1.name.filter(isOver30),
age: object1.age.filter(isOver30),
salary: object1.salary.filter(isOver30)
}
...or less duplicative:
const thoseOver30 = Object
.entries(object1)
.map(([prop, array]) => ({ [prop]: array.filter(isOver30) }))
.reduce((result, props) => Object.assign(result, props), {});
An easy to understand solution:
const maxAge = 30;
const object = {
name: ['David', 'Juan', 'Simon', 'Lukas'],
age: [41, 22, 33, 50],
salary: [100, 80, 120, 150]
};
const result = { name: [], age: [], salary: [] };
for (let i = 0; i < object.name.length; i++) {
if (object.age[i] <= maxAge) {
result.name = [...result.name, object.name[i]];
result.age = [...result.age, object.age[i]];
result.salary = [...result.salary, object.salary[i]];
}
}
console.log(result);
You could create one object where keys are indexes of the elements where age >= 30 and then use that object as hash table for filtering.
const data = {
name: ['David', 'Juan', 'Simon', 'Lukas'],
age: [41, 22, 33, 50],
salary: [100, 80, 120, 150]
}
const hash = data.age.reduce((r, e, i) => {
if (e >= 30) r[i] = true;
return r;
}, {})
for (let i in data) {
data[i] = data[i].filter((_, j) => hash[j])
}
console.log(data)
You could also use different data structure to get an array of objects with reduce method and then just apply filter.
const data = {
name: ['David', 'Juan', 'Simon', 'Lukas'],
age: [41, 22, 33, 50],
salary: [100, 80, 120, 150]
}
const result = Object
.entries(data)
.reduce((r, [k, v]) => {
v.forEach((e, i) => {
if (!r[i]) r[i] = {}
r[i][k] = e;
})
return r;
}, [])
.filter(({ age }) => age >= 30)
console.log(result)

Comparing two arrays with objects with unordered keys

I know they're several questions that indicate how to do this, however, when the keys of the objects are in a different order the provided solutions do not work.
let array1 = [
{ name: 'David', age: 30 },
{ name: 'Amy', age: 39 }
];
let array2 = [
{ age: 30, name: 'David' },
{ age: 39, name: 'Amy' }
];
Comparing the arrays
console.log(array1.every((value, index) => {
return JSON.stringify(value) === JSON.stringify(array2[index]);
})
// Returns false
// Expected true
Understandably these two arrays are different but the data is the same. So...
How do I compare arrays with objects in which I cannot guarantee that the keys are ordered identically?
You can do a proper object comparison, there are a lot of ways to do that.
Here's one of the examples:
let array1 = [
{ name: 'David', age: 30 },
{ name: 'Amy', age: 39 }
];
let array2 = [
{ age: 30, name: 'David' },
{ age: 39, name: 'Amy' }
];
console.log(array1.every((value, index) =>
Object.keys(value).length === Object.keys(array2[index]).length &&
JSON.stringify(value) === JSON.stringify({...value, ...array2[index]})
));
1) Convert array of objects to array of strings
2) Compare both array of strings (one way is to do with reduce as below).
let array1 = [
{ name: "David", age: 30 },
{ name: "Amy", age: 39 }
];
let array2 = [
{ age: 30, name: "David" },
{ age: 39, name: "Amy" }
];
const isEqual = (arr1, arr2) => {
if (arr1.length !== arr2.length) {
return false;
}
const toStr = ({ name, age }) => `${name}-${age}`;
const a1 = Array.from(arr1, toStr);
const a2 = Array.from(arr2, toStr);
return a1.every(item => a2.includes(item));
};
console.log(isEqual(array1, array2));

Categories