This question already has answers here:
JavaScript merging objects by id [duplicate]
(18 answers)
How can I merge properties of two JavaScript objects dynamically?
(69 answers)
Closed 6 years ago.
Suppose we have a java script objects on array like this:
lets say i have a variable books having collection of book
var books ={
{
id: 1,
name: 'Physics'
}
{
id: 2,
name: 'Mathematics'
}
{
id: 3,
name: 'Chemistry'
}
}
And lets say every writer have a book name inside their info like this
var writers ={
{
id: 123,
name: 'William Jeff',
book: 'Physics'
},
{
id: 123123,
name: 'John Doe',
book: 'Mathematics'
},
{
id: 1212312323,
name: 'asd Doe',
book: 'Chemistry'
},
{
id:123123,
name: 'ASD DAS',
book:'Physics'
}
}
I want to merge these javascript objects to this one :
var result = {
{
id: 1,
name: 'Physics',
writers : {
{
id: 123,
name: 'William Jeff',
},
{
id:123123,
name: 'ASD DAS',
}
},
{
id: 2,
name: 'Mathematics'
writers : {
{
id: 123123,
name: 'John Doe',
}
},
}
{
id: 3,
name: 'Chemistry',
writers : {
{
id: 1212312323,
name: 'asd Doe',
},
},
}
}
I tried using underscore foreach but it gets terribly complicated like too much loop inside loop. I think there are certainly good way to do it :)
Is there anyway?
Thanks
You can iterate both objects if they have an id:
var books = { 1: { id: 1, name: "Math" }, ...}
var writers = { 1: { id:1, name: "John Doe", book: "Math"}, ...}
Or declare them as arrays:
var books = [{ id: 1, name: "Math" }, ...]
var writers = [{ id:1, name: "John Doe", book: "Math"}, ...]
Then you can do do the for-loops
var result = {}; //or as an array
for(bookKey in books){
var book = books[bookKey];
for(writerKey in writers){
var writer = writers[writerKey];
if(writer.book == book.name){
result[bookKey] = { //for an array: result.push(object)
id: book.id,
name: book.name,
writer: {
id: writer.id,
name: write.name
}
}
}
}
}
As an object result[1] will be the book with id 1.
As an array result[0] will be the book with id "X".
Related
This question already has answers here:
How to convert an array into an object in javascript with mapped key-value pairs?
(4 answers)
How do I convert array of Objects into one Object in JavaScript?
(17 answers)
Closed last month.
Is it possible to map an array of objects with custom keys? Here's the outcome that I would like to have:
{ 4: Hotel, 3: Mall, 2: Resort, 1: Restaurant, 5: Staycation, 6: Store }
What I got:
[ "4: Hotel", "3: Mall", "2: Resort", "1: Restaurant", "5: Staycation", "6: Store" ]
The code:
// this data actually comes from a database
const categories = [
{ id: 4, name: "Hotel" },
{ id: 3, name: "Mall" },
{ id: 2, name: "Resort" },
{ id: 1, name: "Restaurant" },
{ id: 5, name: "Staycation" },
{ id: 6, name: "Store" },
];
console.log(
categories.map((category) => {
return category.id + ": " + category.name;
})
)
Use reduce instead of map to keep the output to a single object instead of an array.
const categories = [
{ id: 4, name: "Hotel" },
{ id: 3, name: "Mall" },
{ id: 2, name: "Resort" },
{ id: 1, name: "Restaurant" },
{ id: 5, name: "Staycation" },
{ id: 6, name: "Store" },
];
// this data actually comes from a database
const c = categories.reduce((acc, category) => {
acc[category.id] = category.name;
return acc;
}, {});
console.log(c);
This question already has answers here:
How to insert an item into an array at a specific index (JavaScript)
(28 answers)
Closed 8 months ago.
I have an array like the following
const inputArray = [
{
_id: "D01",
name: "Sky",
},
{
_id: "D02",
name: "Space",
},
{
_id: "D03",
name: "Black",
},
{
_id: "D04",
name: "Yello",
},
];
How to write a function so that I can insert another object say,
const dataToBeInserver = {
_id: "A01",
name: "Watch",
};
to a specified index, lets say at index 2.
Thanks!
simply slice the parts and insert the desired array in the middle, just follow the code for reference. Thanks!
const inputArray = [
{
_id: "D01",
name: "Sky",
},
{
_id: "D02",
name: "Space",
},
{
_id: "D03",
name: "Black",
},
{
_id: "D04",
name: "Yello",
},
];
const dataToBeInserver = {
_id: "A01",
name: "Watch",
};
const indexWhereToInsert = 2;
const finalObject = [
...inputArray.slice(0, indexWhereToInsert),
dataToBeInserver,
...inputArray.slice(indexWhereToInsert),
];
console.log(finalObject);
I have a following array
const _array = [{id: 1, name: 'Adam'}, {id:3, name: 'Crystal'}, {id:2, name: 'Bob'}, {id: 4, name: 'Daisy'}];
How to write a single line of code in typescript to get item where name equal to Crystal from the array?
You can use array find method like following:
const _array = [
{ id: 1, name: "Adam" },
{ id: 3, name: "Crystal" },
{ id: 2, name: "Bob" },
{ id: 4, name: "Daisy" },
];
const item = _array.find((item) => item.name === "Crystal");
console.log(item);
Output
{ id: 3, name: 'Crystal' }
Yes I am aware of similar questions but it doesn't quite cover my use case here.
I'm having trouble finding a way to bring the time complexity of this down
I have two objects like so
const people = [
{
name: 'Steve',
id: 1,
fruitInBasket: 6
},
{
name: 'James',
id: 2,
fruitInBasket: 4
}
]
const homes = [
{
id: 1,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Steve',
id: 1
}
]
},
{
id: 2,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Steve',
id: 1
}
]
}
]
so one is a collection of people with a count of fruit in a basket and the other is a collection of homes and within each home is the same users as in the people collection.
Now I want to order the users in each home based on the count of fruitInBasket so I have done this
// create an empty table to store the order of the people
let orderTable = {};
// order the people based off the count in fruitInBasket using lodash orderBy
people = orderBy(people, ['fruitInBasket'], ['desc']);
// create the table
orderTable = people.reduce((acc, item, index) => {
return {
...acc,
[item.id]: index
}
}, {});
// order the people in each home based on the order in the `orderTable`
homes.forEach((home) => {
let members = [];
home.familyMembers.forEach((member) => {
let i = orderTable[member.id];
members[i] = member;
});
home.familyMembers = members;
})
so immediately you can see a nested for loop - which is never ideal.. but I can't figure out a way around this. This method has to sort through quite a lot of data and I am noticing huge performance issues.
Any help would be appreciated!
This should be O(N log N). Its performance bottleneck is the one time sort. Everything else is just O(N) iteration. Some microoptimizations still possible.
Generate an ordered map lookup table.
Just move arrays based on that mapping.
There is a hpc sort library that is measured around 10-40x faster than built-in JavaScript on benchmarks that can be added to increase performance.
I'm not sure, but is the familyMember table the same for every home object? Can you not just copy the same familyMember array to every object or do they have different properties?
Extra optimization per home could be to convert above table to index to index mapping, so that native level array indexing will be used for subsequent ordering.
const orderMap = Object.fromEntries(people.sort((x,y)=>x.fruitInBasket-y.fruitInBasket).map(({id},i)=>[id,i]))
// O(N)+O(NlogN)
homes.forEach(home=>{
const {familyMembers:fms} = home
const arr = new Array(fms.length)
//may want to prefill to maintain PACKED array: https://v8.dev/blog/elements-kinds#avoid-creating-holes
for(const fm of fms) arr[ orderMap[fm.id] ] = fm
home.familyMembers = arr
})
// map lookup O(N)
console.log(homes)
<script>
const people = [
{
name: 'Steve',
id: 1,
fruitInBasket: 6
},
{
name: 'James',
id: 2,
fruitInBasket: 9
}
]
const homes = [
{
id: 1,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Steve',
id: 1
}
]
},
{
id: 2,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Steve',
id: 1
}
]
}
]
</script>
You can filter and sort:
const people = [
{
name: 'Steve',
id: 1,
fruitInBasket: 6
},
{
name: 'James',
id: 2,
fruitInBasket: 4
},
{
name: 'Cesar',
id: 3,
fruitInBasket: 14
}
]
const homes = [
{
id: 1,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Cesar',
id: 3
},
{
name: 'Steve',
id: 1
}
]
},
{
id: 2,
familyMembers: [
{
name: 'James',
id: 2
},
{
name: 'Steve',
id: 1
}
]
}
]
homes.forEach(function(home){
home.familyMembers.sort((a,b)=>people.find(x=>x.id == a.id).fruitInBasket - people.find(x=>x.id == b.id).fruitInBasket)
})
console.log(homes)
Explanations:
You will iterate through homes:
homes.forEach(function(home){
You will sort the members:
.familyMembers.sort((a,b)
To sort, you have to get the fruits of the members, so you find the correct ID then take the correct property:
people.find(x=>x.id == a.id).fruitInBasket
Then you compare:
(a,b)=>people.find(x=>x.id == a.id).fruitInBasket - people.find(x=>x.id == b.id).fruitInBasket
If what you're looking for is performance, you should change people strucutre:
const people = {
1: {
name: 'Steve',
fruitInBasket: 6
},
2: {
name: 'James',
fruitInBasket: 4
}
}
This way you can retrieve fruits more easily:
people[id].fruits
Also, if your "id" is defined somewhere, don't define it in another place. Your homes should look like this:
const homes = {
1: {
familyMembers: [1, 2, 3]
},
2: {
familyMembers: [1,2]
}
}
So your algorithm goes like this:
const people = {
1: {
name: 'Steve',
fruitInBasket: 6
},
3: {
name: 'James',
fruitInBasket: 4
},
2: {
name: 'Cesar',
fruitInBasket: 9114
}
}
const homes = {
1: {
familyMembers: [1, 2, 3]
},
2: {
familyMembers: [1,2]
}
}
Object.keys(homes).forEach(function(k){
homes[k].familyMembers.sort((a,b)=>people[a].fruitInBasket - people[b].fruitInBasket)
})
console.log(homes)
This question already has answers here:
Aggregating object values of JavaScript arrays?
(2 answers)
Closed 4 years ago.
I have an Array of objects, for example:
[{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
}, {
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
}, {
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}]
I need to sum the points for each person, the problem I´m facing is there are more than 50 different person names so I can´t do something like this
for (let i = 0; i < issues.length; i++) {
if (issues[i].name == 'mike') {
//////////////////////
}
}
Because the API in future can return a new Person.
You can reduce into an object indexed by name:
const input = [{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
},
{
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
},
{
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}];
const points = input.reduce((a, { name, points }) => (
Object.assign(a, { [name]: (a[name] || 0) + points })
), {});
console.log(points);
If you do not want to use reduce and keep things simple you can still use a forEach loop as below:
const input = [{
name: 'mike',
id: 3312,
points: 2,
summary: 'example',
},
{
name: 'andrew',
id: 4123,
points: 1,
summary: 'example',
},
{
name: 'mike',
id: 0522,
points: 5,
summary: 'example',
}];
var res = {};
input.forEach((obj) => {
res[obj.name] = res[obj.name] ? res[obj.name]+obj.points : obj.points;
});
console.log(res);