testSed4 = sedenia4.get(0);
while (it8.hasNext()) {
tempRozdiel = it8.next();
tempSed4 = it7.next();
if (testSed4.equals(tempSed4)) {
testSed4 = tempSed4;
casy.add(tempRozdiel);
} else {
casy.add(hodnota);
testSed4 = tempSed4;
}
}
for (int j = 0; j < casy.size(); j++) {
System.out.println(casy.get(j) + " casy");
}
Why I have error in line: tempRozdiel = it8.next();
What is bad in this code ?
Exception happens because you are modifying the collection over which it is iterating within the body of the iteration loop.
This is a reason why you got ConcurrentModificationException from iterator.next()
while (it8.hasNext()) {
tempRozdiel = it8.next();
tempSed4 = it7.next();
You are only checking if it8 has a next element, but not for it7.
Furthermore, you cannot use casy.add() if it7 or it8 are iterators on this object.
Related
how do I pull variables from array one by one? I want to make a card with one saying Zlin, second Praha, etc... The way it works now is that it outputs all of them at once 4x. Thank you.
const KartyLoop = () => {
var mesta = ['Zlin','Praha','Ostrava','Brno']
var lokace = []
for (var i=0; i < mesta.length; i++)
{
lokace += mesta + "\n"
}
return (<Text>{lokace}</Text>);
}
Your code pushes the array itself and not its values.
If I understand correctly you want to copy an array.
You would want to do this.
const KartyLoop = () => {
var mesta = ['Zlin','Praha','Ostrava','Brno']
var lokace = []
for (var i=0; i < mesta.length; i++)
{
lokace += mesta[i] + "\n"
}
return (lokace);
}
Building a Sort-Visualizer in React using the Create-React-App [https://roy-05.github.io/sort-visualizer/ ]
I'm animating each iteration of the loop using setTimeouts. On dev console I get the following warning:
Line 156:32: Function declared in a loop contains unsafe references to variable(s) 'minimum', 'minimum', 'minimum', 'minimum' no-loop-func
Here's the code-snippet:
for(let i=0; i<arr.length-1; i++){
let minimum = i; //Declare minimum here
setTimeout(()=>{
for(let j = i+1; j<arr.length; j++){
setTimeout(()=>{
//Getting a warning for these references:
array_bar[j].style.backgroundColor = 'red';
array_bar[minimum].style.backgroundColor = 'blue';
setTimeout(()=>{
if(arr[j] < arr[minimum]){
array_bar[minimum].style.backgroundColor = 'lightblue';
minimum = j;
}
else{
array_bar[j].style.backgroundColor = 'lightblue';
}
}, 4);
}, (j-1)*4);
}
Going through ESLint Docs, I believe the issue might be that i'm modifying the value inside the setTimeout but the variable is declared outside its scope.
I'm not sure how to fix that warning, any help will be appreciated!
Note: Here's the entire function if you need it -
selectionSort(){
const arr = this.state.array,
array_bar = document.getElementsByClassName("array-elem");
this.setState({startedSelectionSort: true});
for(let i=0; i<arr.length-1; i++){
let minimum = i; //Declare minimum here
setTimeout(()=>{
for(let j = i+1; j<arr.length; j++){
setTimeout(()=>{
//Getting a warning for these references:
array_bar[j].style.backgroundColor = 'red';
array_bar[minimum].style.backgroundColor = 'blue';
setTimeout(()=>{
if(arr[j] < arr[minimum]){
array_bar[minimum].style.backgroundColor = 'lightblue';
minimum = j;
}
else{
array_bar[j].style.backgroundColor = 'lightblue';
}
}, 4);
}, (j-1)*4);
}
setTimeout(()=>{
let temp = arr[i],
arr1_height = arr[minimum],
arr2_height = arr[i];
arr[i] = arr[minimum];
arr[minimum] = temp;
array_bar[i].style.height = `${arr1_height}px`;
array_bar[minimum].style.height = `${arr2_height}px`;
array_bar[i].style.backgroundColor = "green";
if(i !== minimum){
array_bar[minimum].style.backgroundColor = 'lightblue';
}
}, 400);
if(i === arr.length-2){
setTimeout(()=>{
array_bar[i+1].style.backgroundColor = "green";
},800);
}
}, i*400);
}
setTimeout(()=>{
this.setState({sorted: true})
}, arr.length*400+1750);
}
I also encountered same warning. In my case, I declared variable outside the iteration, but modified variable inside forEach method.
Something like:
// some code above
let validInputs = true;
someInputs.forEach( input => {
validInputs = input.value && validInputs;
})
After I did some reserch, I found in this post, JSHint error : Functions declared within loops referencing an outer scoped variable may lead to confusing semantics, mentioned that JSHint doesn't like how the anonymous function in there is being re-created over and over.
I changed forEach arrow function to for (let index i = 0; index < someInputs.length; index++), and the warning is gone.
Perhaps in your case, change setTimeout to traditional non-arrow function can remove the warning.
updated on Apr 7th 2021
As I'm reading the Professional JavaScript for Web Developers, 4th edition, I might have found why this warning is implemented in the ESLint.
From section 4.3 Garbage Collection sections, the book mentioned that closure might also lead to memory leak.
The purpose for forEach and arrow function is to limit the scope of the variable, as describes below from MDN:
Arrow functions establish "this" based on the scope the Arrow function is defined within. from Arrow function expressions
In section Creating closures in loops: A common mistake, MDN mentioned:
Another alternative could be to use forEach() to iterate over the helpText array and attach a listener to each , as shown:
function showHelp(help) {
document.getElementById('help').textContent = help;
}
function setupHelp() {
var helpText = [
{'id': 'email', 'help': 'Your e-mail address'},
{'id': 'name', 'help': 'Your full name'},
{'id': 'age', 'help': 'Your age (you must be over 16)'}
];
helpText.forEach(function(text) {
document.getElementById(text.id).onfocus = function() {
showHelp(text.help);
}
});
}
setupHelp();
In our implementation, calling arrow functions inside forEach is creating closure of closure, which obviously can create some confusing semantics for garbage collection.
You're correct that modifying the variable inside setTimeout is causing the issue. You can get around this by wrapping setTimeout inside a promise and waiting for it to resolve before modifying your variables. This is much cleaner using async/await:
for (let i = 0; i < arr.length - 1; i++) {
let minimum = i;
await new Promise(resolve => setTimeout(resolve, i * 400));
for (let j = i + 1; j < arr.length; j++) {
array_bar[j].style.backgroundColor = "red";
array_bar[minimum].style.backgroundColor = "blue";
await new Promise(resolve => setTimeout(resolve, (j - 1) * 400));
if (arr[j] < arr[minimum]) {
array_bar[minimum].style.backgroundColor = "lightblue";
minimum = j;
}
}
}
With each loop, you're creating a promise that resolves once the timeout is expired. Using await will pause execution of your function until the promise resolves. Then, you can modify variables like minimum because they are no longer within the scope of the callback function you were originally passing into setTimeout.
Using typescript and React, I was able to initialize minimum inside of the for loop call, and then reinitialize once I got inside:
for (let i, minimum = 0; i < arr.length - 1; i++) {
minimum = i; //reinitialize minimum here
setTimeout(() => {
for (let j = i + 1; j < arr.length; j++) {
setTimeout(() => {
//Getting a warning for these references:
array_bar[j].style.backgroundColor = "red";
array_bar[minimum].style.backgroundColor = "blue";
setTimeout(() => {
if (arr[j] < arr[minimum]) {
array_bar[minimum].style.backgroundColor = "lightblue";
minimum = j;
} else {
array_bar[j].style.backgroundColor = "lightblue";
}
}, 4);
}, (j - 1) * 4);
}
});
}
For me redeclaring the variables in the timeout function did remove that warning for me in FirebaseFunctions.
setTimeout(async ()=> {
var NumberInst = await admin
.firestore()
.collection("CollName")
.doc('DocName')
.get();
var Numbers = NumberInst.data().postponeX;
}, 1000 * 60 * 11 );
checkGridData(name: string, searchObj: ElementArrayFinder) {
if (name != "") {
let counter = 0;
let beforesplit = name;
let aftersplit = beforesplit.split("|");
var countval = searchObj.count();
return searchObj.count().then((count) => {
for (let i = 0; i < aftersplit.length; i++) {
let countval = searchObj.count();
// expect(count).toBe(expectedRecords[i]);
for (let j = 0; j < count; j++) {
searchObj.get(j).getText().then(function (text) {
if (text.indexOf(aftersplit[i]) !== -1) {
expect(text).toContain(aftersplit[i]);
++counter
//console.log("counter inside loop is" + counter)
}
return counter;
});
}
}
});
}
}
I am new to protractore. I wrote a function below
I am calling this in another function.
var abc = this.CheckGridData(ProductData.AddEquipment.EquipmentSelection, ProductObj.ele_equipmentvalidation)
console.log("Counter value returned:" + abc)
And i am getting this error
Counter value returned:ManagedPromise::5760 {[[PromiseStatus]]: "pending"}
I tried to do promise but I don't know how to do resolve promise. How to resolve inside for loop in the above, so that i can use it and know the concept? I tried various site but i couldn't understand how to resolve.
Because the function CheckGridData return a promise, so the variable abc is a promise.
To consume the eventual value of promise, you have to use then() as below:
checkGridData(name: string, searchObj: ElementArrayFinder) {
if (name != "") {
let counter = 0;
let beforesplit = name;
let aftersplit = beforesplit.split("|");
return searchObj.getText().then((texts) => {
// texts is an string array of text of all elements of searchObj
for (let i = 0; i < aftersplit.length; i++) {
if(texts.includes(aftersplit[i])) {
++counter;
}
}
return counter;
};
}
}
var abc = this.CheckGridData(ProductData.AddEquipment.EquipmentSelection,
ProductObj.ele_equipmentvalidation)
abc.then(function(count){
console.log(count);
})
I am trying to get a simple ES6 for-loop working but cant figure out why its not running.
I've copied an example from developer.mozilla docs and I've also tried it with the eslinter version which is below:
I have also added a let i = 0; above. All it renders/logs is i = 0 and wont increment.
the eslint version is here: eslint site
for (i = 0; i < 10; i += 1) {
console.log('i', i);
return <p>component {i}</p>;
}
Edit: ok got the values coming back in the log as i=0, i=1, etc... but to get them into a component each? i tried the push into array and mapping through to get the components out but i get no error and nothing appearing, even if i try just getting a value out.
const nbPageArray = [];
let i = 0;
for (i = 0; i < nbPages; i += 1) {
console.log('i', i);
nbPageArray.push(<p>component {i}</p>);
}
console.log('array', nbPageArray);
nbPageArray.map(a => <p>{a.type}</p>);
}
final working version:
const nbPageArray = [];
for (let i = 0; i < nbPages; i += 1) {
nbPageArray.push({ page: i + 1 });
}
return nbPageArray.map(a =>
<li className="page-item"><a className="page-link">{a.page}</a></li>,
);
Main issue is i += 10;
That should be 1 += 1;
And You should return array of elements :
var p_tags = [];
for (i = 0; i < 10; i += 1) {
console.log('i', i);
p_tags.push(<p>component {i}</p>);
}
return p_tags;
Edited question's answer :
First Error:
const nbPageArray = []; should be var nbPageArray = [];
Second You are not returning the array so change your code to this
return nbPageArray.map(a => <p>{a.type}</p>);
If you return from your for loop, you will exit the current function, you are also incrementing i by 10 each trip so you will exit the loop after one round either way.
If you are trying to print a string with the value of i ten times you could try using template string like so:
for (i = 0; i < 10; i += 1) {
console.log('i', i);
console.log(`<p>component ${i}</p>`);
}
you are returning from the loop and also incrementing by 10. The loop will execute only once.
As said in the comments, the return inside the for loop is going to exit from the function at the first iteration.
You can do something like this instead:
const result = Array(10).fill().map((_, i) =>
<p>component {i}</p>
);
Or
const result = [...Array(10)].map((_, i) =>
<p>component {i}</p>
);
Is there any built-in feature on AngularJS to avoid ng-repeater to receive duplicated entries?
Right now I'm using the following code to prevent it:
$scope.tags = ['black','white','red','yellow','blue'];
$scope.selectedTags = [];
// textarea value
var words = $scope.message.split(' ');
for(var j = 0; j < words.length; j++) {
for (var k = 0; k < $scope.selectedTags.length; k++) {
if ($scope.selectedTags[k].Name == words[j]) {
contains = true;
}
}
if (!contains)
{
$scope.selectedTags.push($scope.tags[i]);
contains = false;
}
}
Angular UI has a unique filter:
Filters out all duplicate items from an array by checking the specified key
Alternatively, if it's just a string array you can filter your array like:
arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});