How to modify object in for loop? React Native - javascript

I am new in react native , I want to insert new value into every object of array.
I have successfully implemented the logic according to object value. Condition is working right, I have checked by console.log() the statement working right but when I print the my final output array the new value of every object is same, value not assign different in object according to condition.
Here is the code which I am using:-
var newOffers = [];
response.data.forEach((element) => {
for (let i = 0; i < element.frequency; i++) {
var offer = element;
if (offer.used == 0) {
offer.isAvailable = "true";
newOffers.push(offer);
} else {
if (offer.frequency - i <= offer.used) {
console.log("True calling", offer.frequency - i);
offer.isAvailable = "false";
newOffers.push(offer);
} else {
console.log("False calling", offer.frequency - i);
offer.isAvailable = "true";
newOffers.push(offer);
}
}
}
});
console.log("All offers ", newOffers);
I have assign "isAvailable" value "true" or "false" to offer object and all condition working perfectly but when I print the "newOffers" array after complete the loop process the all "isAvailable" values is "false"
What wrong with this code? can someone help me?

In javascript when you use = operator for the objects, it doesn't work like as you expect. You should change your code like this if you are familiar with ES6:
var offer = {...element}
or
var offer = Object.assign({}, element);
Read this

Related

JavaScript - IF statement inside FOR loop is outputting both options

I'm writing a function that searches an array from a prompt using an IF statement. So for I get the output I want if it is successful, but it also outputs the failure.
// The array I'm searching through
var statesArray = new Array();
statesArray['WI'] = "Wisconsin";
statesArray['MN'] = "Minnesota";
statesArray['IL'] = "Illinois";
// Now I'm trying to let the user search for the full state name from the two-letter abbreviation.
var stateSearch = prompt("enter a two letter state abbreviation")
for(var key in statesArray){
var value = statesArray[key]
if(stateSearch == key){
alert(value);
}else{
alert("try again");
}
}
So if I type "WI" in the prompt, I get "Wisconsin" and "try again".
Loop is not appropriate for this. Loop will check all values of array and check found or not for all.
var statesArray = new Array();
statesArray['WI'] = "Wisconsin";
statesArray['MN'] = "Minnesota";
statesArray['IL'] = "Illinois";
// Now I'm trying to let the user search for the full state name from the two-letter abbreviation.
var stateSearch = prompt("enter a two letter state abbreviation");
let searchObj =statesArray[stateSearch];
if(searchObj == null){
alert("try again");
}else{
alert(searchObj);
}
Your for loop isn't exiting after it has found a match. Either put it in a function and return when you find a match or break the for loop
for(var key in statesArray){
var value = statesArray[key]
if(stateSearch == key){
alert(value);
break;
}else{
alert("try again");
}
}
function searchArray(arr){
for(var key in arr){
var value = arr[key]
if(stateSearch == key){
return value;
}
}
}
Note: Array was created to store a numbered list of elements. If you need to get values by keywords, it's better idea to use a common object instead:
var statesArray = {
WI: "Wisconsin",
MN: "Minnesota",
IL: "Illinois",
null: "Cancelled!"
};
var abbr = prompt("enter a two letter state abbreviation");
alert( statesArray[abbr] || "try again" );
// will return the value, if `abbr` key exists,
// and "try again" if statesArray[abbr] returned `undefined`
Instead of using a for loop, you could use:
var index = statesArray.indexOf(stateSearch);
which will set index to -1 if the value is not found, otherwise it will be set to the position in the array that the value was found.
Like some of the other comments and answers said, you're not breaking/exiting your loop early when a match is found, which is why you are continuing to iterate through even after you find the right value. Had you searched for MI, for example, you would see:
try again
Minnesota
try again
Firstly, it's generally considered a better practice, from a performance and ease of reading standpoint, to create Array literals than to use the JavaScript new keyword to create an Array instance.
Secondly, JavaScript does not technically allow for Associative Arrays (Hashes/HashMaps) (in other words, arrays with named indices). From the MDN Developer Documentation for Arrays:
Arrays cannot use strings as element indexes (as in an associative array) but must use integers. Setting or accessing via non-integers using bracket notation (or dot notation) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's object property collection.
In your case, I would think a simple object or Map would suit you better. For Map:
// Define the Map.
const statesHashMap = new Map([
['WI', 'Wisconsin'],
['MN', 'Minnesota'],
['IL', 'Illinois']
]);
// You could also do:
statesHashMap.set('TX', 'Texas');
// Attain user input:
const stateSearchKey = prompt("Enter a two letter state abbreviation");
Then, to iterate over and find the right state, you'd have a few different options:
// Iterate with forEach.
statesHashMap.forEach((value, key) => {
if (stateSearchKey === key) {
console.log(value)
}
});
// Iterate with for..of
for (const key of statesHashMap.keys()) {
if (stateSearchKey === key) {
const state = statesHashMap.get(key);
console.log(state);
}
}
The problem with the forEach method above is that you can't break out without throwing an exception, which makes the for..of loop likely more favorable for you. If you want to show a message to the user when they don't get a state, you could use break statements:
// Iterate with for..of
for (const key of statesHashMap.keys()) {
if (stateSearchKey === key) {
const state = statesHashMap.get(key);
console.log(state);
break;
} else {
console.log('Try again');
break;
}
}
Or, to make it look nicer and as a better programming practice, encapsulate the operation in a function and return early when needed:
// Iterate with for..of
const findStateByAbbreviation = abbrev => {
for (const key of statesHashMap.keys()) {
if (stateSearchKey === key) {
const state = statesHashMap.get(key);
return console.log(state);
} else {
return console.log('Try again');
}
}
}
findStateByAbbreviation(stateSearchKey);
You should probably also use .toUpperCase() on the input from the user to ensure you match the key WI (for example) if the user provides wi.
Be wary of browser compatibility with the Map option, however.
Hope this helps.

How to copy the values of an array (not pointing). Slice isn't working for me

I have a function that tries to systematically add arrays to another multidimensional array. At each step of the way the arrays being added are calculated correctly, however, these calculations change the previously entered values. I've tried using slice but I'm clearly doing it wrong :(.
Please see code below - it is the return posMatrix that is being affected.
function allPossibilities(hand) {
var startingHandLength = hand.length;
var potHand = Array.prototype.slice.call(hand);
var scores = new Array();
var posMatrix = new Array();
var nextCard = 1;
var progressStage = true;
var finished = false;
var shallowArr = new Array();
do {
scores = calculateScores(potHand);
var maxScore = Math.max.apply(null, scores)
shallowArr = potHand.slice();
if (maxScore>16.5)
{posMatrix.push([shallowArr,maxScore])
console.log(posMatrix);
debugger;
if (potHand.length !== startingHandLength)
{
do{
if(potHand[potHand.length-1][1] < 10)
{
potHand[potHand.length-1][1]++;
progressStage = true;
}
else {potHand.pop();
potHand[potHand.length-1][1]++;}
}
while(progressStage === false)
}
}
else
{
potHand.push(["Imaginary",1,"Imaginary"]);
}
progressStage=false;
if(potHand.length === startingHandLength)
{finished = true;}
}
while(finished === false);
return posMatrix;
}
If the starting hand > 16.5, the function works as none of the other code gets to run. But otherwise it does not. The final return should be an array where each element is looks like this: [[array],number]. The number seems to come out fine, but since it is not an object it is not affected. I would expect the [array]s to be different from one another, currently they are all the same.
Slice returns a shallow copy of array, since you have multidimensional array so you need to deep clone of array
JSON.parse(JSON.stringify(array))
Or you can use loadash cloneDeep
You made a shallow copy of hand (which, BTW, you should've included). With statements like this
potHand[potHand.length-1][1]++;
you're accessing and modifying elements of hand, too.
Here, potHand[potHand.length-1] is an object, and it's en element of hand (not a copy - the same element).

Arrays in arrays, length always is 0, json not working

I try to create arrays in arrays and then forward it to JSON.
First problem, when i try to use a lista.length or something, console always return 0. I tried to overpass this problem and create another array, but now I have problem with JSON - always return [] - empty lista array.
var lista = [];
var licz = [];
function ListujBledy(value, where) {
var checked = document.getElementById(value).checked;
var desc;
if (value == "blad-tab") {
desc = "Nieprzeźroczysta lista graczy.";
} else if (value == "blad-tab1") {
desc = "Brak listy graczy na początkowym zrzucie ekranu.";
} else if (value == "blad-tab2") {
desc = "Brak listy graczy na końcowym zrzucie ekranu.";
}
if (checked == true) {
if (lista[where] == undefined) {
var temp = [];
temp[value] = desc;
lista[where] = temp;
licz[where] = 1;
} else if (licz[where] == 1) {
var temp = lista[where];
temp[value] = desc;
lista[where] = temp;
licz[where] = 2;
} else if (licz[where] == 2) {
var temp = lista[where];
temp[value] = desc;
lista[where] = temp;
licz[where] = 3;
}
} else {
if (licz[where] == 1) {
delete lista[where];
licz[where] = 0;
} else if (licz[where] == 2) {
delete lista[where][value];
licz[where] = 1;
} else if (licz[where] == 3) {
delete lista[where][value];
licz[where] = 2;
}
}
console.log(lista.length);
console.log(lista);
console.log(JSON.stringify(lista));
console.log("---------------------------------------------------------");
}
Console log from browser:
I don't have more ideas, I can't use lista[0], lista[1] etc. everything must be functional. Eveyrthing is taken from variables but everywhere I was looking for information about it, everybody using numbers in key or permanent keys.
Editied version of code:
I know that checked could have been better done, so I corrected it here.
https://jsfiddle.net/5vdgLtue/1/
The main problem is that even if I do this https://jsfiddle.net/5vdgLtue/0/ the array returns this element, but the length function says it is 0.
It looks like you might be starting out with javascript. Keep in mind that you haven't actually called the function at any point in your code. Is that the case or are you not sharing the full code you have run?
There is only one condition in which the array 'lista' could gain value: if 'check'== true and 'where' == undefined.
In that scenario, you declare the array 'temp' and declare temp[value]= desc. However, if 'value' contains a value different than "blad-tab", "blad-tab1" or "blad-tab2", 'desc' remains empty therefore temp[value] has a name but no value. You are then assigning a named valueless item to lista[where] which would explain why your console displays content but no length. btw, this would be easier if you named your variable something other than 'value' .
Problem is your selector points to the parent element. In jquery you could do this less code but assuming you're not using jQuery. Try something like:
function getDesc(chkboxName) {
var checkboxes = document.getElementsByName(chkboxName);
//or use getElementsbyClassName...
var checkboxesChecked = [];
// loop over them all
for (var i=0; i<checkboxes.length; i++) {
// And stick the checked ones onto an array...
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i]);
}
}
for (var i=0; i<checkboxesChecked.length; i++) {
if (checkboxesChecked[i].value === "blad-tab") {
desc = "Nieprzeźroczysta lista graczy.";
} else if (checkboxesChecked[i].value === "blad-tab1") {
desc = "Brak listy graczy na początkowym zrzucie ekranu.";
} else if (checkboxesChecked[i].value === "blad-tab2") {
desc = "Brak listy graczy na końcowym zrzucie ekranu.";
}
}
return desc;
}
This should answer most of your questions.
In summary:
In javascript there are 2 types of arrays: standard arrays and associative arrays
[ ] - standard array - 0 based integer indexes only
{ } - associative array - javascript objects where keys can be any strings
What you are doing is using array in an associative manner. Basically, you are adding properties to your array objects, unlike a standard array where you would only assign values by zero-indexed numbers like temp[0]='something', lista[1]='some other thing' etc.
If you want the length of the key set of the array, then you can use Object.keys(lista).length. This should solve your problem.

BOOLEAN not working after adding FOR LOOP JavaScript

I'm working on an assignment where a boolean has to switch after a variable is matched to a value in an array. The variable has to be matched with the value in the array using a for loop. However, I'm able to switch the boolean before I introduce the for loop. But after I introduce the for loop, the boolean is stuck to its original value of false.
Can somebody explain why this is happening?
Can I also request, I'm not looking for 'how to do this' but rather an explanation as to why is it happening - so I will appreciate if you do not recommend to me 'another better way' of achieving this - I just want to understand the concept as I'm a beginner.
The code I'm using before the for loop (which changes the boolean correctly) is:
var c = 3;
var w = [];
var m = false;
w.push(3,4);
if (c === w[0]){
m = true;
}
alert (m);
However after I add the for loop counter and also change the if condition from c===w[0] to c===w[i], I only get the 'false' alert using the below code:
var c = 3;
var w = [];
var m = false;
w.push(3,4);
for (i=0; i<2 && c!==w[i]; i++){
if (c === w[i]){
m = true;
}
}
alert (m);
Instead of using for loop, if you only wish that the boolean variable must be switched on satisfying only one condition, you can use some() method. Using this, the loop will not iterate through all the objects and will stop once your condition is satisfied. Example shown below:-
var arr = [3,4,5];
var m = 4;
var bool = false;
array.some(function(item) {
if (m === item){
bool = true;
}
});
alert(bool);
So this will basically give you alert true once you get the matching object from an array.
The condition from for is checked also before first iteration, so the if is not fired. Check out code like this:
var c=3;
var w=[];
w.push(3,4);
var m=false;
for (var i=0;i<2 && c!==w[i];i++){
console.log('In loop')
if (c===w[i]){
m=true;
}
}

How to search in complex javaScript array object

I am a bit confused. I have the following code in the directive:
NavTabsDirective.prototype.addPane = function (pane) {
if (!_.isObject(pane) || "Pane" !== pane.constructor.name) {
throw new TypeError("pane must be an instance of Pane");
}
if (_.isUndefined(this.FirstPane)) {
this.FirstPane = pane;
}
this.Panes[pane.name] = pane;
};
when I look in the debugger at the this.Panes array, I see something like:
this.Panes[name1] = paneObject -- with properties
this.Panes[name2] = paneObject -- with its properties
I want to understand how to search this array. Say, this is my code:
let invalid = (_.findIndex(this.Panes, { 'isValid': false })>=0);
which I commented out as it could not find a pane where isValid is false although I can see such pane in that array.
So, my confusion comes from the fact that the Panes array object has names to access each pane object and so I don't know how to properly search it. How would I check for invalid among the panes?
Unless pane.name is a number the panes in this.panes is not an array, it's an object, you can use it's keys and reduce it to a value:
const result = Object.keys(this.Panes).reduce(
(all,key)=>all && this.Panes[key].isValid,
true
)
Figured out a solution after checking few threads here:
for (let pane in this.Panes) {
if (this.Panes[pane].isValid === false) {
invalid = true;
break;
}
}
It works nicely.
var Panes = ["Hello","World"];
var PanesLength = Panes.length;
for (var i = 0; i < PanesLength; i++) {
if(Panes[i] == "Hello"){
alert(Panes[i]);
}
}

Categories