Changing a value inside the array in a forEach() loop - javascript

Message: This is a function I'm going to implement in my very first project (Which is a point-of-sale system) using Vue Js and I wrote this function using pure JavaScript to simplify this question. So I'd be really grateful if somebody could help me with this problem so I can continue building my practice project. Thanks ❤️
My code explanation: I have an empty array called newArray.And an array called mainArray with some records. And I've included a button with an onClick event that triggers the function clicked() with an argument passed to it, which is 2 in this case.
What I'm expecting to get: I want to check for a record inside the newArray which contains an id with 2. If such a record is found, I want to add the stock value by 1 in the record. If such a record is not found inside the newArray loop through the mainArray and copy the record which has the id of 2 and add it to the newArray and reset the stock to 1 (So when we click the button again, the record which has id 2 is already there inside the newArray, therefore, I want to add 1 to it, So the stock: 2 now). I have attempted on this problem, and I have attached the code.
Summary according to my project: I have looped through mainArray in my project, so each record has a button with clicked() function, with an attribute called productId, productId is passed as the argument to the clicked() function, I'm expecting: If I click on a button it takes productId as the argument and the function loops through the newArray finding for a record which has id equal to the productId If such record is there add stock by 1. If such record is not there grab the record from the mainArray which has the id equal to the productId value and put inside the newArray by setting the stock value to 1 (stock: 1). So when I click the same button which has the same attribute value it will add 1 to the stock in the record of the same value equal to the id inside the newArray (therefore the stock: 2 now) If again click stock will be stock: 3 so on adding by 1.
function clicked(inp){
const newArray = [];
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
newArray.forEach((item) => {
if(inp == item.id){
item.days = item.days + 1;
} else {
mainArray.forEach((element) => {
if(inp == element.id){
newArray.push(element);
}
});
}
});
console.log(newArray);
}
<button id="1" onClick="clicked(2)">Click me</button>

Suggestion : move newArray outside the clicked function as it is going to update on click.
Implementation : You can use Array.filter() method on newArray to check if record as per the input id is available or not and then by using Array.find() you can do filtering on the mainArray if there is no data in newArray.
Live demo :
const newArray = [];
function clicked(inp){
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const findInNewArr = newArray.filter(item => inp === item.id);
if (findInNewArr.length) {
newArray[0].stock += 1;
} else {
const findInMainArray = mainArray.find(element => inp === element.id);
if (findInMainArray) {
findInMainArray.stock = 1;
newArray.push(findInMainArray);
}
}
console.log(newArray);
}
<button id="1" onclick="clicked(2)">Click me</button>

This is what I really expected (Thanks to Rohìt Jíndal for giving me the idea of doing this)
const newArray = [{ id: 1, name: "Shoes",stock: 1, price: 10 }];
function clicked(inp){
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const findInNewArr = newArray.filter(item => inp === item.id);
if (findInNewArr.length > 0) {
newArray.forEach((element) => {
if(element.id === inp) {
element.stock += 1;
}
});
} else {
const findInMainArray = mainArray.find(element => inp === element.id);
if (findInMainArray) {
findInMainArray.stock = 1;
newArray.push(findInMainArray);
}
}
console.log(newArray);
}
<button id="1" onclick="clicked(2)">Click me</button>

In your code forEach function will not be executed, because newArray is empty, so there is nothing to iterate through.
You might use findIndex to loop through newArray and then check if index is greater than -1. That would mean that array contains object with specified id.
function clicked(inp){
const newArray = [];
const mainArray = [
{ id: 1, name: "Shoes",stock: 5, price: 10 },
{ id: 2, name: "Bag",stock: 10, price: 50 },
];
const inputIndex = newArray.findIndex((item) => item.id === inp);
if (inputIndex > -1) {
newArray[inputIndex].stock = newArray[inputIndex].stock + 1;
} else {
mainArray.forEach((element) => {
if(inp == element.id){
newArray.push(element);
}
});
}
console.log(newArray);
}

you can find inp in 2 arrays, then update or create new element for newArray
const newArray = [];
const mainArray = [{
id: 1,
name: "Shoes",
stock: 5,
price: 10
},
{
id: 2,
name: "Bag",
stock: 10,
price: 50
},
];
function clicked(inp) {
let exist = newArray.find(ele => ele.id === inp)
if(exist) {
exist.stock++
} else {
let {id,name, price} = mainArray.find(ele => ele.id === inp)
exist = {id,name, price, stock: 1};
newArray.push({...exist})
}
console.log('newArray :', newArray)
console.log('mainArray :', mainArray)
}
<button id="1" onClick="clicked(2)">Click me</button>

Related

Use array find() method instead of for loop

How can we use Array.find() method instead of for loop in this code ?
onLoadTickets() {
const ticketsReq = this.ticketService.getTickets();
const tariffsReq = this.tariffService.getTariffs();
forkJoin([ticketsReq, tariffsReq]).subscribe(results => {
const data = results[0];
const tariffResp = results[1];
this.tickets = data.requests;
for (let i = 0; i < this.tickets.length; i++) {
for (let j = 0; j < tariffResp.tariffs?.length; j++) {
if (tariffResp.tariffs[j].id == this.tickets[i].tariffId) {
this.tickets[i].tariff = tariffResp.tariffs[j]
}
}
}
});
}
Note :
Using find() method is not mandatory. I have to write this code with any array methods.
Edit :
I have used map() and includes() methods. my solution:
const tariffIds = tariffResp.tariffs.map((tariff: Tariffs) => tariff.id);
this.tickets.map((item) => {
if (tariffResp.tariffs === null || tariffResp.tariffs === undefined) {
return item;
}
if (tariffIds.includes(item.tariffId)) {
item.tariff = tariffResp.tariffs[tariffIds.indexOf(item.tariffId)];
}
return item;
});
This works but I'm not sure it's the best solution
Array.find() method returns the first element in the provided array that satisfies the provided testing function.
So, if in your case you only have one tariff against all the tickets then you can go ahead with Array.find() but if you have multiple tariff and multiple tickets then you can go ahead with Array.filter().
Demo with Array.find() :
const tickets = [{
tariffId: 1,
name: 'Ticket 1'
}, {
tariffId: 2,
name: 'Ticket 2'
}];
const tariffResp = {
tariffs: [{
id: 1
}]
};
const result = tickets.find((obj) => tariffResp.tariffs[0].id);
console.log(result);
Demo with Array.map() along with Array.filter() :
const tickets = [{
tariffId: 1,
name: 'Ticket 1'
}, {
tariffId: 2,
name: 'Ticket 2'
}, {
tariffId: 3,
name: 'Ticket 3'
}];
const tariffResp = {
tariffs: [{
id: 1
}, {
id: 2
}]
};
const result = tariffResp.tariffs.map((obj) => {
return tickets.filter((ticketObj) => obj.id === ticketObj.tariffId);
});
console.log(result);
this.tickets=data.request.map(x=>{
const obj:any=x;
obj.tariff=tariffResp.find(t=>t.id==x.tariffId)
return obj
})
You loop over data.request using map. map transform an array in another
First you create an object with the values of x
After you add a new propety "tariff" that is the "tariffResp" who has the "id" property equal to the property "tariffId" of x
Check find and map methods of an array

How can we print value from an array if two array matches with some value in JavaScript?

I have to compare two array of objects and check if the same item includes in the other array.
const array1 = [
{ item: "orange", id: 11 },
{ item: "apple", id: 12 },
];
const array2 = [10, 11, 12];
If I am checking with a value from array2 in array1.How can I get output like below when mapping array2?
Item does'nt exists
orange
apple
Here's a way using Map, though with a bit of tweaking it could use a normal object instead of Map. The map indexes the items in array1 by id and then allows you to look for the item in the map (using has() or get()); if it doesn't exist you can fall back to the default string. ?? is the nullish coalescing operator and it allows you to give a term for the expression should the value before ?? be null or undefined.
const array1 = [{ item: "orange", id: 11 }, { item: "apple", id: 12 }];
const array2 = [10, 11, 12];
const default_string = "Item does'nt exists";
const array1_map = new Map(array1.map((o) => [o.id, o]));
const res = array2.map( (id) => array1_map.get(id)?.item ?? default_string );
console.log(res);
Try this
const array1 = [{
item: 'orange',
id: 11
}, {
item: 'apple',
id: 12
}]
const array2 = [10, 11, 12]
for (const x of array2) {
//find element from array
const searchElem = array1.find((item) => item.id == x)
if (searchElem) {
console.log(searchElem.item + " for " + x)
} else {
console.log("Item doesn't exists for", x)
}
}
You can easily achieve this result using map and find
const array1 = [
{ item: "orange", id: 11 },
{ item: "apple", id: 12 },
];
const array2 = [10, 11, 12];
const result = array2.map((id) => {
const itemFound = array1.find((o) => o.id === id);
if (itemFound) return `${itemFound.item} for ${itemFound.id}`;
else return `Item does'nt exists for 10`;
});
console.log(result);
The easiest way to get common items by comparing two array in JavaScript is using filter() and includes() array functions.
For example:
const array1 = [
{ item: "orange", id: 11 },
{ item: "apple", id: 12 },
];
const array2 = [10, 11, 12];
const matchedArray = array1.filter((item) => array2.includes(item.id));
console.log(matchedArray);
We don't need to use for loop, forEach, map and find functions.
Try this code I think it will solve your problem
I have written some comments on javascript code it may help you.
const array1=[{item:'orange', id:11},{item:'apple', id:12}]
const array2=[10,11,12]
function removeDuplicates(array, matchKey) {
return array.filter((value, index) => {
return array.indexOf(array.find(value_1 => value_1[matchKey] == value[matchKey])) == index
});
}
// send "id" parameter if you want to filter array by id
// ex: removeDuplicates(array1, 'id')
const filteredArray1 = removeDuplicates(array1, 'item');
array2.forEach(id => {
let foundItem = array1.find(itemObj => itemObj.id == id);
if(foundItem == null) {
console.log(`Item doesn't exists for ${id}`);
}else {
console.log(`${foundItem.item} for ${id}`);
}
});
If I understand the question correctly what you want to do is confirm if an object with a certain property exists in Array 1 for each element in Array 2.
If you want to check each and see if it exists you can do this:
const fruits = [
{item: 'orange', id: 11},{item: 'apple', id: 12}
]
const fruitIds = fruits.map((fruit) => fruit.id);
const ids = [10, 11, 12]
ids.forEach((id) => {
console.log(`${id} exists in fruits: ` + fruitIds.includes(id))
})
Or if you wish to check if there is a fruit for each ID in the array and you only care about true / false if all exist or not then you can do:
const fruits = [
{item: 'orange', id: 11},
{item: 'apple', id: 12}
]
const fruitIds = fruits.map((fruit) => fruit.id).sort();
const ids = [10, 11, 12];
console.log("There is a fruit for each ID in ID array: ", JSON.stringify(ids) === JSON.stringify(fruitIds))
If this does not answer your question then please edit and try to make your question clearer and I'll do the same with my answer.
Note that the last snippet is just one way to compare arrays or objects in JavaScript.

How to dedupe an array of objects by a key value pair?

// This is a large array of objects, e.g.:
let totalArray = [
{"id":"rec01dTDP9T4ZtHL4","fields":
{"user_id":170180717,"user_name":"abcdefg","event_id":516575,
}]
let uniqueArray = [];
let dupeArray = [];
let itemIndex = 0
totalArray.forEach(x => {
if(!uniqueArray.some(y => JSON.stringify(y) === JSON.stringify(x))){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
node.warn(totalArray);
node.warn(uniqueArray);
node.warn(dupeArray);
return msg;
I need my code to identify duplicates in the array by a key value of user_id within the objects in the array. Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this? I am struggling to figure out how to path the for each loop to identify the dupe based on the key value instead of the entire object.
Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this?
Don’t compare the JSON representation of the whole objects then, but only their user_id property specifically.
totalArray.forEach(x => {
if(!uniqueArray.some(y => y.fields.user_id === x.fields.user_id)){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
You could take a Set and push to either uniques or duplicates.
var array = [
{ id: 1, data: 0 },
{ id: 2, data: 1 },
{ id: 2, data: 2 },
{ id: 3, data: 3 },
{ id: 3, data: 4 },
{ id: 3, data: 5 },
],
uniques = [],
duplicates = [];
array.forEach(
(s => o => s.has(o.id) ? duplicates.push(o) : (s.add(o.id), uniques.push(o)))
(new Set)
);
console.log(uniques);
console.log(duplicates);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way is to keep a list of ids you found so far and act accordingly:
totalArray = [
{ id: 1, val: 10 },
{ id: 2, val: 20 },
{ id: 3, val: 30 },
{ id: 2, val: 15 },
{ id: 1, val: 50 }
]
const uniqueArray = []
const dupeArray = []
const ids = {}
totalArray.forEach( x => {
if (ids[x.id]) {
dupeArray.push(x)
} else {
uniqueArray.push(x)
ids[x.id] = true
}
})
for (const obj of uniqueArray) console.log("unique:",JSON.stringify(obj))
for (const obj of dupeArray) console.log("dupes: ",JSON.stringify(obj))

append array by index in nested array of object

I created a sample code to demo my problem, the actual data is much bigger
const arr = [{
id: 1
}, {
id: 2,
items: [{
id: 1
}]
}]
const target = 2
const nextIndex = 1
newArr = arr.map(o => o.id === target ? ({
...o,
items: [...o.items, {
id: 'new id'
}]
}) : o);
console.log(newArr);
How to insert {id: 'new id'} by index? Above code is appending onto items array. Assuming I have a click event, user can insert the position of {id: 'new id} by index, I can't use append as it doesn't replace existing object.
expected output
[{
id: 1
}, {
id: 2,
items: [{
id: 1
},{
id: 'something'
}]
Above code doesn't work, adding new item to items array without using index.
Try to pass index from onClick event
functionName = (i) => { //where i is index from onclick event
arr.map( o, index) => {
if(i === index)
{
const obj = { //object
id: 'new id'
}
arr[i].push(obj) // push object at given index from onClick
}
}
}
The splice() method changes the contents of an array by removing or replacing existing elements and/or adding new elements
const target = 2;
int index = arr.findIndex(v => v.id == target);
if (index > -1) {
arr.splice(index, 1, {id: 'new id'}); // replace 1 with 0 if you just want to insert.
}

how to count duplicate values object to be a value of object

how to count the value of object in new object values
lets say that i have json like this :
let data = [{
no: 3,
name: 'drink'
},
{
no: 90,
name: 'eat'
},
{
no: 20,
name: 'swim'
}
];
if i have the user pick no in arrays : [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
so the output should be an array
[
{
num: 3,
total: 11
},
{
num: 90,
total: 1
},
{
num:20,
total: 4
}
];
I would like to know how to do this with a for/of loop
Here is the code I've attempted:
let obj = [];
for (i of arr){
for (j of data){
let innerObj={};
innerObj.num = i
obj.push(innerObj)
}
}
const data = [{"no":3,"name":"drink"},{"no":90,"name":"eat"},{"no":20,"name":"swim"}];
const arr = [3,3,3,3,3,3,3,3,3,3,3,20,20,20,20,80,80];
const lookup = {};
// Loop over the duplicate array and create an
// object that contains the totals
for (let el of arr) {
// If the key doesn't exist set it to zero,
// otherwise add 1 to it
lookup[el] = (lookup[el] || 0) + 1;
}
const out = [];
// Then loop over the data updating the objects
// with the totals found in the lookup object
for (let obj of data) {
lookup[obj.no] && out.push({
no: obj.no,
total: lookup[obj.no]
});
}
document.querySelector('#lookup').textContent = JSON.stringify(lookup, null, 2);
document.querySelector('#out').textContent = JSON.stringify(out, null, 2);
<h3>Lookup output</h3>
<pre id="lookup"></pre>
<h3>Main output</h3>
<pre id="out"></pre>
Perhaps something like this? You can map the existing data array and attach filtered array counts to each array object.
let data = [
{
no: 3,
name: 'drink'
},
{
no:90,
name: 'eat'
},
{
no:20,
name: 'swim'
}
]
const test = [3,3,3,3,3,3,3,3,3,3,3,90,20,20,20,20]
const result = data.map((item) => {
return {
num: item.no,
total: test.filter(i => i === item.no).length // filters number array and then checks length
}
})
You can check next approach using a single for/of loop. But first I have to create a Set with valid ids, so I can discard noise data from the test array:
const data = [
{no: 3, name: 'drink'},
{no: 90, name: 'eat'},
{no: 20, name: 'swim'}
];
const userArr = [3,3,3,3,3,3,3,3,7,7,9,9,3,3,3,90,20,20,20,20];
let ids = new Set(data.map(x => x.no));
let newArr = [];
for (i of userArr)
{
let found = newArr.findIndex(x => x.num === i)
if (found >= 0)
newArr[found].total += 1;
else
ids.has(i) && newArr.push({num: i, total: 1});
}
console.log(newArr);

Categories