JavaScript for loop is pushing duplicates - javascript

I originally used for/of, like so:
for (let item of totalData) {
if (item) {
let comp1 = item.slice(0,item.length/2)
let comp2 = item.slice(item.length/2)
for (let char of comp1) if (comp2.includes(char)) {
arr.push(char)
}
}
}
I noticed that I was getting the wrong results, so I started console logging the char and the item. This led me to notice that there were items in the first array (totalData) for which this code was running multiple times.
Thus, I tried doing it the original way, changing it to for (let i = 0; i < totalData.length; i++) and assigning item as totalData[i]. This didn't change anything.
Finally, I tried this code:
let arr = [];
for (let i = 0; i < totalData.length; i++) {
let item = totalData[i];
if (item && item != totalData[i - 1]) {
let comp1 = item.slice(0,item.length/2)
let comp2 = item.slice(item.length/2)
for (let char of comp1) if (comp2.includes(char)) {
arr.push(char)
console.log(char,item)
}
}
}
It came out with seemingly just as many (97, although I guess I didn't check how many there were before) duplicates.
Is this a bug in devtools or did I do something wrong? I'm using Brave (Chromium) devtools to run this code.
Edit: to make this more reproducible, here's my full code with a fake array (because the array I'm using is way too long)
let totalData = ['testingt','stringhere','doesntmatttr'];
let arr = [];
for (let item of totalData) {
if (item) {
let comp1 = item.slice(0,item.length/2)
let comp2 = item.slice(item.length/2)
for (let char of comp1) if (comp2.includes(char)) {
arr.push(char)
}
}
}
console.log(totalData.length, arr.length)
Running this in my console, I got 3 and 5. Here's a screenshot of what happened with the data I was originally using:
Those strings (minus the characters at the beginning, those were the results) all appeared in my dataset, but only once each.
Edit 2: I'm trying to figure out what characters in each string are on both sides of it. The expected output for the example I gave (the arr) would be ['t','r','t'].

Okay I figured it out while responding to people because it made me look at the question more from an objective viewpoint rather than from the viewpoint of someone who's tryna make the code work.
The problem is that some of the strings in my data array (e.g. "cNzPBNpclllzHbmTNRhqCRTgjC") have a character on the first side of the string twice, and also have it on the second side. So, for this string, it would push "N" twice, because it's checking for each character in the first side of the string (so both Ns) whether or not one exists on the second side (and there is an N on the second side).
Fixed code:
for (let i = 0; i < totalData.length; i++) {
let item = totalData[i];
if (item && item != totalData[i - 1]) {
let comp1 = item.slice(0,item.length/2)
let comp2 = item.slice(item.length/2)
for (let char of comp1) if (comp2.includes(char)) {
arr[i] = char
}
}
}

Related

How to store components in an array and render them when I need in React?

I want to render x numbers times a specific component according to what the user chooses.
I wrote this function:
const generateShiftsForm = (totalWeeks) => {
const shiftWeeks = 1;
const shiftList = [];
for (let i = shiftWeeks; i === totalWeeks; i++) {
shiftList.push(<ShiftForm totalMinutes={totalMinutes} setTotalMinutes={setTotalMinutes}/>);
}
return shiftList;
};
But when I call it inside the render function it doesn't generate anything unless the totalWeeks is 1.
{generateShiftsForm(shiftNumber).map((form) => (form))}
Why is it like this? I didn't get it, can someone explain it to me?
Seems like there is a typo in the for loop condition - i === totalWeeks, that's why the for loop is being run only once and only if totalWeeks equals 1. Try replacing the for loop you have with the following:
for (let i = shiftWeeks; i <= totalWeeks; i++) {...}

React - For Loop conditional render - not working and infinite trigger

I am trying to dynamically multiple an item in my render based on a variable kind of like this
<div>
<Multiple
multiple={props.multiple}
base1={props.base1}
exp1={props.exp1}
/>
</div>
const Multiple = (props) => {
let result = "";
let wtf = "";
console.log("test"); // gets triggered
for(let i = 0; i < props.multiple; i++){
console.log("i: "+i); // gets triggered
result.concat("{props.base1} +"); // this doesn't work for some reason
wtf = i; // gets triggered
}
console.log("result: "+result); // result is blank
console.log("wtf:" +wtf);
return <span>{result}</span>;
}
PROBLEM 1: Even though I am entering the for-loop, my result is not being changed and i don't understand why.
Also since I cant get it to work yet, I wanted to ask: If i do it this way, where I am concatenating {props.base1} as a string, when i return it in the render, will it show up as "{props.base1}" or will it render as the variable value?
Here is an example as to what it should look like:
base1 = abc
multiple = 2
resulting render should look like:
abc + abc +
Will concatenating my prop into a string before rendering result it in looking like this instead of the above block?
{props.base1} + {props.base1} +
PROBLEM 2: EDIT ALSO, for some reason everything in the <Multiple> component is infinitely triggering, which I also do not understand why it is happening
You are using concat, which doesn't update the original string, it creates a new string instead. What you could do is either
let result = '';
for(let i = 0; i < props.multiple; i++) {
console.log("i: "+i); // gets triggered
result += `${props.base1} `;
wtf = i; // gets triggered
}
console.log(result);
As far as the infinite loop problem goes, what actually is props.muitlple? Is it an array or a string? If so, you should change your loop to
for(let i = 0; i < props.multiple.length; i++)
Edit: if props.multiple is a number, i < props.multiple should work, you should log the value in your component and check once.
The result string is not being properly appended to
const Multiple = (props) => {
let result = "";
let wtf = "";
for(let i = 0; i < props.multiple; i++){
result += props.base1.toString() + "+"
}
console.log("result: "+result);
return <span>{result}</span>;
}
For the infinite loop I would check it's values before entering the loop to make sure your bounds are properly set.
// add this line before for loop
console.log(props.multiple)
a. change to result.concat('${props.base1} + '); (backtics!!)
b. i think that maybe there is a problem with the props you pass to <Multiple ... >. check again their value, maybe log their value.

Infinite Loop for finding a power set for a string

I'm working on a problem where I need to find all the power set of a given string which are all the possible subsets. I feel like I'm close with my current code but I can't figure out why I'm getting stuck on an infinite loop for my second iteration. I ran it through the debugger but I still can't seem to figure it out even though I'm sure it's very simple. When i = 0 then it goes to the second loop where j = 0 && j < 1 so for example if help is my given str argument then I would expect it to add j + '' and push it into my allSubsets array. The problem is that the j iteration will keep looping and doing j++ and will never stop. I'm not sure why this is. One particular question even if I solve this infinite loop - do I need to update the allSubsets.length in the iteration to keep it updated with the pushed in strings?
var powerSet = function(str) {
let allSubsets = [''];
for (let i = 0; i < str.length; i++) {
debugger;
for (let j = 0; j < allSubsets.length; j++) {
allSubsets.push(sortLetters(str[i] + allSubsets[j]));
}
}
return allSubsets;
};
var sortLetters = (word => {
//convert string to an array
//use the sort to sort by letter
//convert array back to string and return
return word.split('').sort().join('');
})
Everytime you push to allSubSets, the length increases, and thus, your loop never ends. A declarative loop runs on the range of the initial loop. See below for a fix based on your code:
var powerSet = function(str) {
let allSubsets = [''];
for (let i = 0; i < str.length; i++) {
allSubsets.forEach( (_char, j) => { // declarative loop here
allSubsets.push(sortLetters(str[i] + allSubsets[j]));
})
}
return allSubsets;
};
var sortLetters = (word => {
return word.split('').sort().join('');
})
From MDN web docs:
The range of elements processed by forEach() is set before the first invocation of callback. Elements which are appended to the array after the call to forEach() begins will not be visited by callback. If existing elements of the array are changed or deleted, their value as passed to callback will be the value at the time forEach() visits them; elements that are deleted before being visited are not visited. If elements that are already visited are removed (e.g. using shift()) during the iteration, later elements will be skipped. (See this example, below.)
See the fourth paragraph under descriptions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Description

Apps Script JS adding items to array from range (if not already in array) fails

I am looping through various cells and want to add their string content do an array, if the content is not already in the array. It works perfectly fine when I do it manually like so, trying to add 'eJobs' to the array (see below "var item = 'eJobs') which already containts 'eJobs':
var divisionarray = ['eJobs']
for (var i = 0; i < cells_users.length-1; ++i) {
var row_users = cells_users[i];
if (row_users[0] == user_ldap) {
var podarray = row_users[1].split(', ')
for (j = 0; j < podarray.length; j++) {
for (var k = 0; k < cells_edit.length; ++k) {
var row_edit = cells_edit[k]
if (podarray[j] === row_edit[0]) {
var item = 'eJobs'
if (!(divisionarray.indexOf(item) >= 0)) {
divisionarray.push(item)
}
}
}
}
Logger.log(divisionarray)
As expected, the log file shows [17-10-08 19:11:04:111 BST] [eJobs], illustrating that the code works and 'eJobs' has not been added to the array as it is already in the array.
Now, when I change var item='eJobs' to values of a range
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
the code does not work anylonger, as the log file shows:
[17-10-08 19:14:03:770 BST] [eJobs, eJobs, BestJobs, Vivre Deco, ...
Note I have a range of thousands of cells, so I get alot of duplicates added. What am I missing? Note the cells of the defined range are indeed just strings with a single word (e.g. 'eJobs').
The code is working and the log file is indicating what the problem is..
[eJobs, eJobs, BestJobs, Vivre Deco,
In the second eJobs there is a white space before eJobs, so the first value and the second value don't match.
Without seeing your data and going by the 'just strings with a single word' I would say that using a .replace(" ", "") on the text string should work, this will find the first " " in the string and remove it. I.e. " eJobs" would become "eJobs".
2.
Is this line of code just for testing? You should never use a method like this in a script. It will be extremely inefficient
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
Instead get the full range using .getValues()and iterate over it then.
3.
Is there a reason you are using === in if (podarray[j] === row_edit[0]) unless you need to check for type always use ==

Javascript array splice in animation

I'm currently working on a map generator in canvas.
Here is the code working code : http://jsfiddle.net/RtPmm/
and the piece that raise an issue :
MapBuilder = function(){
...
this.checkPath = function(){
...
(logic condition ...) {
var i = Game.builders.indexOf(this);
Game.builders.splice(i,1); /!\
}
and in the render function :
for (var i = 0, len = Game.builders.length; i < len; i++) {
Game.builders[i].checkPath();
}
My problem is that when my MapBuilder objects are supposed to be remove from the array, the animateloop function still find deleted index when it iterate throughGame.builders array.
I can't really find this out..
Thanks for taking the time to leave an answer (or comment)
Well, it's because you are looping until the initial length of the array is reached, but the length changes as you remove items and the items gets shifted.
There are several solutions to this problem, like looping backward instead, or something like:
var builders = Game.builders,
builder;
for (var i = 0, len = builders.length; i < len; i++) {
(builder = builders[i]).checkPath();
if (builders[i] !== builder) {
//builder was removed, fix the loop
--i; --len;
}
}

Categories