Multiple iterations of one array js - javascript

I have an array
const head = [
{
"id": 1,
"name": "AK47",
"norms": "15-18",
"times": 2
},
{
"id": 2,
"name": "Deagle",
"norms": "13-21",
"times": 1
}
]
arrays should be created from it according to the number of times properties
Something like that:
const tail = [
{
"id": 1,
"headId": 1,
"time": 1,
"check": 16,
"status": "ok"
},
{
"id": 2,
"headId": 1,
"time": 2,
"check": 14,
"status": "less"
},
{
"id": 3,
"headId": 2,
"time": 1,
"check": 23,
"status": "excess"
}
]
"times": 2 was therefore 2 arrays created. Inside them is the property time meaning which time of times
How can I implement this solution more conveniently and correctly. I will be glad for any help

Your explanation is still a bit unclear, but from what I've understood, the code below might be the answer you're looking for. It loops through the head elements and then loops x number of times, where x equals the times property. It creates an array for each element in head and then flattens it to generate the desired 1D array output.
const head = [{
"id": 1,
"name": "AK47",
"norms": "15-18",
"times": 2
},
{
"id": 2,
"name": "Deagle",
"norms": "13-21",
"times": 1
}
];
let idIdx = 1;
const res = head.flatMap((obj) => {
let arr = [];
for (let i = 0; i < obj.times; i++)
arr.push({
id: idIdx++,
headId: obj.id,
time: i + 1
});
return arr;
});
console.log(res);

Related

Check if array of objects, which also contain nested arrays with objects, are the same, if so, combine them into one object and add the keys together

I would need to check if the objects in the "food" array are equal to each other, and the ones that are - combine into one adding amount and mody.amount and leaving the rest unchanged. This is just for better order data displaying. I tried with lodash library and reduce but but I don't know exactly how to construct this function that nested objects(mody) adds values ​​as well, and in case isEqual returns false keep the object while concurrently concatenating the identical ones.
What I tried:
obj1.reduce((prev, next) => _.isEqual(prev, next) ? {...prev, amount: prev.amount + next.amount} : next
Now it looks like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 1,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 1
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 1
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
and would need something like that:
const food = [
{
"id": 1,
"name": "chicken",
"price": 6,
"amount": 2,
"mody": [
{
"id": 33,
"name": "cheese",
"price": 1,
"amount": 2
},
{
"id": 34,
"name": "chips",
"price": 2,
"amount": 2
}
]
},
{
"id": 2,
"name": "pizza",
"price": 6,
"amount": 2,
"mody": [
{
"id": 12,
"name": "extra cheese",
"price": 2,
"amount": 1
}
]
}
]
The algorithm to sum the food amounts and mody amounts are almost the same, the difference is that for each food that has the same id we will sum the mody amount. To make the algorithm simpler I used a dictionary as the accumulator on the reduce function so we have a unique element per key. This element will be our final food or mody with the amount sum.
Mody sum algoritm:
const sumMody = (modyAccumulator, currentMody) => {
//Get the stored mody in the accumulator dictionary or null if it the mody is not stored
const storedMody = modyAccumulator[currentMody.id] ?? null
// if mody is null then add mody to the dictionary using its id as key
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
//Mody is stored then sum amount
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
The food sum algoritm is the same as the sumMody, the only difference is that it calls the sumMody function when the foods are equal:
const sumFood = (foodAccumulator, currentFood) => {
//Get the stored foodin the accumulator dictionary or null if it the food is not stored
const storedFood = foodAccumulator[currentFood.id] ?? null
// if food is null then add food to the dictionary using its id as key
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
//Food is stored then sum food amount
storedFood.amount += currentFood.amount
//Create a list with mody from both foods
const modyList = [...storedFood.mody, ...currentFood.mody]
//Use reduce passing the sumMody callback function and initialize the accumulator with a dictionary
const modySumDictionary = modyList.reduce(sumMody, {})
/* The function above return a dictionary where the identifier is the mody.id
and the value is the mody. We only need the values from that dictionary so
we use Object.values to extract all the values. */
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
To execute both sums:
//As explained before the reduce function will return a dictionary so we use Object.values to get only the values
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Algoritm without comments:
const sumMody = (modyAccumulator, currentMody) => {
const storedMody = modyAccumulator[currentMody.id] ?? null
if (!storedMody) {
modyAccumulator[currentMody.id] = currentMody
} else {
storedMody.amount += currentMody.amount
}
return modyAccumulator
}
const sumFood = (foodAccumulator, currentFood) => {
const storedFood = foodAccumulator[currentFood.id] ?? null
if (!storedFood) {
foodAccumulator[currentFood.id] = currentFood
} else {
storedFood.amount += currentFood.amount
const modyList = [...storedFood.mody, ...currentFood.mody]
const modySumDictionary = modyList.reduce(sumMody, {})
storedFood.mody = Object.values(modySumDictionary)
}
return foodAccumulator
}
const result = Object.values(food.reduce(sumFood, {}))
console.log(result)
Reference to Object.values

Copy second nested array of objects into first nested array of objects

How can I assign key value from array of object to another array object
I would like to assign the key:value pair to the existing array of object from the another array of objects.
I have check this thread but it is not working in my case.
I have tried something like this but that is not returning the desired output that I am looking for.
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
let result;
var A1 = DataA.options.map((v) => {
console.log(v);
result = v;
})
var A2 = DataB.options.map(v => {
result.options = v;
console.log("result",result);
})
let arr3 = DataA.options.map((item, i) => Object.assign({}, item, DataB[i]));
console.log(arr3);
Result will be I need as below:
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A", "value": 10 },
{ "id": 2, "name": "Type B", "value": 20 },
{ "id": 3, "name": "Type C", "value": 30 }]
}
I need to merge the deep clone of the array that is slightly different from this thread.
The linked duplicate does actually address your question, but you need to adjust it to your situation and not just copy paste.
DataA.options = DataA.options.map((item, i) => Object.assign({}, item, DataB.options[i]));
but since this mutates the original DataA object anyway, you may as well just use forEach() and avoid creating the intermediate array from .map().
DataA.options.forEach((item, i) => Object.assign(item, DataB.options[i]));
Both of the above assume that the options arrays of both objects are a. of the same length, and b. sorted by id. To avoid these assumptions you can use .find() to look for matching elements instead of relying on index.
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
const DataA = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
console.log(DataA)
.as-console-wrapper { max-height: 100% !important; top: 0; }

Multiply the object properties

someone tell me how to multiply object's properties? I need this object multiplied by the count of property price and put together
var menu = [
{
"id": 5,
"price": 13,
"count": 2
},
{
"id": 8,
"price": 7,
"count": 3
},
{
"id": 9,
"price": 17,
"count": 1
}
]
var sum = 0;
for (var key in menu) {
for (var key1 in menu[key]) {
//console.log(key1);
if (key1 == 'price'){
price += menu[key][key1];
}
}
}
but I have no idea how to multiply count property
You can use Array.prototype.map with Array.prototype.reduce.
.map takes a callback function which will multiply the price of each item by the count and creates a new array looking like this:
[26,21,17].
.reduce takes a callback as well, iterating over the new create array summing up the multiplied prices resulting to:
64
let menu = [
{
"id": 5,
"price": 13,
"count": 2
},
{
"id": 8,
"price": 7,
"count": 3
},
{
"id": 9,
"price": 17,
"count": 1
}
]
let sum = menu.map(p => p.price * p.count).reduce((a,b) => a + b)
console.log("Total:",sum)
You probably want something like this:
{
"id": 5,
"price": 13,
"count": 3,
"value": function() {return this.price * this.count;}
}
You can do that by either making an object and adding a prototype (which saves memory and time) or construct it that way each time.
Otherwise you can just do:
var obj = { ... } // your stuff
alert(obj.price * obj.count)
suppose you want to calculate the sum
var menu = [
{
"id": 5, "price": 13, "count": 2 }, {
"id": 8, "price": 7, "count": 3 }, { "id": 9, "price": 17, "count": 1 } ];
var sum = 0, item;
for(item in menu)
{
sum += menu[item].price * menu[item].count;
}
console.log(sum);

Return filtered array with only elements that match given value

I want a method that goes through a posts array, and returns a new array with only the elements that match a certain value of the userId property.
For example:
let postsArr = [
{
"userId": 1,
"id": 1
},
{
"userId": 1,
"id": 2
},
{
"userId": 2,
"id": 3
},
{
"userId": 2,
"id": 4
},
{
"userId": 3,
"id": 5
}
]
Say I want to return only the items with userId: 2.
(Something like...)
let filteredArr = postsArr.method( post => post.userId === 2)
Which would (ideally) return:
[
{
"userId": 2,
"id": 3
},
{
"userId": 2,
"id": 4
}
]
I'm sure it would be something like .map() or .filter(), but I can quite get my head round how to do it, or what the best method is in this case.
Any help appreciated.
Your pretty much there to be honest..
let postsArr = [
{
"userId": 1,
"id": 1
},
{
"userId": 1,
"id": 2
},
{
"userId": 2,
"id": 3
},
{
"userId": 2,
"id": 4
},
{
"userId": 3,
"id": 5
}
];
var farray = postsArr.filter((a) => a.userId === 2);
console.log(farray);
In ES5. We used to do this.
var newarray = postsArr.filter(function(obj){
return obj.userId === 2
})

Adding items to different objects in a double for loop - Javascript

It's confusing to try to explain, but I want to be able to add a list of skill sets to different people objects that are in their own list.
For example:
I have a Json object of people:
"people": [
{
"id": 1,
"name": "Tony Rogers",
},
{
"id": 2,
"name": "Steven Grant",
},
{
"id": 3,
"name": "Peter Wilson",
},
]
and then I have a list of skills that I want to match up with them:
"skills": [
{
"id": 1,
"name": "Engineering",
"personId": 1
},
{
"id": 2,
"name": "Painting",
"personId": 2
},
{
"id": 3,
"name": "Chemistry",
"personId": 3
},
{
"id": 4,
"name": "Physics",
"personId": 1
},
]
but I am unsure how to get the output I want by looping through both lists. I would preferably like to append a "skills" section onto each person that contains all of their skills.
I thought I could do something along the lines of
people.forEach(function(person){
skills.forEach(function(skill){
if(skill.personId == person.id){
person['skills'] = {"name" : skill.name};
}
});
});
but it repeats a person multiple times rather than adding to their own skill list.
You need an array type to store multiple skills, so instead of just assigning person['skills'] = {"name" : skill.name}; create an array and push the new skill object to it.
people.forEach(function(person){
skills.forEach(function(skill){
if(skill.personId == person.id){
//creates an array, if not yet created
person['skills'] = person['skills'] || [];
//push the skill object to the array
person['skills'].push(skill.name);
}
});
});
If you have 20 persons and 20 skills, then it will be 20 * 20 = 400 loops!
You can do it more efficiently using just 2 loops:
var skillsByPerson = {};
skills.forEach(function(skill) {
var personId = skill.personId;
var personSkills = skillsByPerson[personId] || (skillsByPerson[personId] = []);
personSkills.push({ name: skill.name });
});
people.forEach(function(person) {
person.skills = skillsByPerson[person.id] || [];
});
Here is the jsPerf test proof for performance check.
You're overwriting skills on each iteration (this part: person['skills'] = {"name" : skill.name};), instead you need to push a skill into an array of skills:
var people = [
{"id": 1, "name": "Tony Rogers",},
{"id": 2, "name": "Steven Grant",},
{"id": 3, "name": "Peter Wilson",}];
var skills = [{
"id": 1,
"name": "Engineering",
"personId": 1
}, {
"id": 2,
"name": "Painting",
"personId": 2
}, {
"id": 3,
"name": "Chemistry",
"personId": 3
}, {
"id": 4,
"name": "Physics",
"personId": 1
}, ]
people.forEach(function(person) {
person['skills'] = []; // create an empty skills array for each person
skills.forEach(function(skill) {
if (skill.personId == person.id) {
person['skills'].push({"name": skill.name}); // push the skill
}
});
});
console.log(people);

Categories