Two strings print as same but don't pass equality test? - javascript

I have a google script that reads in two files and checks for equality between them. When I log the values checked they are the same but my code doesn't work.
for(var i = 1; i < partData.length; i++){
Logger.log("Part Data" + partData[1][2]);
Logger.log("Name" + name);
if(partData[1][2] === name)
{
temp = i + 1;
}
}
Log:
[18-07-13 06:56:15:876 PDT] Part DataES002-101
[18-07-13 06:56:15:877 PDT] NameES002-101
Why are "ES002-101" and "ES002-101" not equal?? They are from different sheets and the same font, although one is smaller and bold but that shouldn't matter right?

Try using the code as follows:
partData[1][2].toString().trim() == name.toString().trim()
If still doesn't work then try using the following:
partData[1][2].toString().replace(/ /g,'')==name.toString().replace(/ /g,'')
I have just tried converting the objects into the string and replaced all spaces to compare. But you should be careful using the above condition as this doesn't compare the real strings.

Related

Short-Circuiting to Print Every Value

Here is my code:
for (let i = 0; i <= 100; i++) {
let output = "";
if (i % 3 === 0) {
output += "Cool";
}
if (i % 5 === 0) {
output += "Breeze";
}
console.log(output || i);
}
In this code, I use a for loop to vary the value of the binding i from 0 to 100.
In the first if statement, I use the modulo and the addition assignment operator to add the string "Cool" to the binding output.
In the second if statement, I use the modulo and the addition assignment operator to add the string "Breeze" to the binding output.
The function of my last statement in the body of my for loop is to print the value of the output binding in the browser console. I do this through short-circuiting. Now, I understand the logic of short-circuiting with the "OR" operator, since the interpreter will short-circuit its full logic of comparing both operands and automatically choose the operand on the left if it can be converted to true, which strings and numbers can, so the operand output is always going to be chosen.
What I don't understand is why short-circuiting is needed to visibly print every value in the console. If I were to use the statement console.log(output); it consolidates the number type values, stating how many were printed in a row before it had to print a string.
Can someone please explain this logic? Why is short-circuiting needed here to prevent the consolidation?
If I were to use the statement console.log(output); it consolidates the number type values, stating how many were printed in a row before it had to print a string.
In case it isn't clear to others, what you're referring to is this:
This is an artifact of the browser console, which consolidates duplicate logs together, to make debugging easier. Here, it's consolidating the duplicate logged empty strings. It's not a issue with your code's logic. If you were to log the output by any other method, the blank outputs would be displayed serially, as you'd expect, rather than being clumped together:
const table = document.querySelector('table').children[0];
for (let i = 0; i <= 100; i++) {
let output = "";
if (i % 3 === 0) {
output += "Cool";
}
if (i % 5 === 0) {
output += "Breeze";
}
table.innerHTML += `<tr>Cell value: ${output}</tr>`;
}
<table>
<tbody>
</tbody>
</table>
Your code is perfectly fine, you just need to find a way to display it other than console.log so that its unintuitive clumping doesn't mess things up.
You can also turn off the grouping by unchecking "Group Similar":

Does anyone know why this problem with math and local storage is occurring?

I'm trying to create a javascript/HTML game where points can be saved over multiple visits to the site, and the save function is working just fine, but when I turn that into a points variable on the load up of the page, the += operator will not work. Instead of using addition to update the variable, it will just add the number to the end of the variable's value. an example of this would be if you said 100 += 1 so that it would make sense for the output to be 101, but instead, it will be 1001.
I have figured out that it is, in fact, the local storage. If just set the points that I'm trying to display to 0 instead of a past score achieved it works fine. This error could possibly be occurring because I am using free web hosting with repl.it so I am sharing a domain with a lot of other sites. I thought about testing if it would work better with cookies but I have never used cookies so I thought I would check here first before trying to learn them.
var points = 0;
points += localStorage.points;
// The below is tied to a save button
function saveData() {
localStorage.points = points;
}
/*This is also tied to a button with an amount of one, and this is
where errors occur. */
function addPoints(amount) {
points += amount;
}
sorry if it's sloppy, I'm kind of new to both javascript and game development. Also, I did, in fact, have a checker to see if local storage was available.
localStorage always stores values as strings. Excerpt from mozilla:
The keys and the values are always strings (note that, as with objects, integer keys will be automatically converted to strings).
You need to first cast points to a number.
var points = 0;
points += +localStorage.points; // + casts it to a number
All data stored in localStorage is a string (or undefined).
So, instead of doing addition, the += operator will do string concatenation.
Try this: points += +localStorage.points or points += Number(localStorage.points)
You also have to make sure the initial value is not undefined.
The full solution would be:
var points = 0;
if (localStorage.getItem('points') !== null) {
// ^^ Similar to localStorage.points !== undefined
points += +localStorage.points; // Now points won't be type-casted to string
}
function saveData() {
localStorage.points = points;
}
/*This is also tied to a button with an amount of one, and this is
where errors occur. */
function addPoints(amount) {
points += amount;
}
To understand why that happens run this example:
const p = 0;
const s = '1';
const n = 1;
console.log(`p + s = ${p + s}, ${typeof(p+s)} | p + n = ${p + n}, ${typeof(p+n)} | p + +s = ${p + +s}, ${typeof(p + +s)}`);

Javascript Editing Text file - Remove all empty lines but one

I just started learning Javascript and I am trying to implement a project that came into my mind. The project is a simple text editor that takes a text as an input does some corrections and posts an output with the fixed text.
The input text is imported as an array. Each line of the text is an object property. The inputText is for displaying the default text in the browser inside a div, and the outputText is the one I use for the editing.
inputText = loadStrings("v.txt");
outputText = inputText;
Now the input text has some sentences. The problem is that there are a lot of empty lines in between.
firstLine
secondLine
thirdLine
What I want to achieve, is to remove all empty lines, but one, so the output text looks like:
firstLine
secondLine
thirdLine
I am searching for a solution for almost 3 days now. I have managed to remove ALL empty lines, but that's not what i want. I want to remove empty lines if they are more than one, but don't make any change if there is only one empty line.
This piece of code is one of many i have tried. This will remove ALL empty lines:
(source: Remove empty elements from an array in Javascript )
outputText = outputText.filter(function(e){
return e.replace(/[\r\n]+/g, '\n')});
Here is the codepen with all HTML, CSS and the JS code I am using.
https://codepen.io/theokondak/pen/KrNNVz
Try this regex:
e.replace(/([\r\n]){2,}/g, '\n\n')});
This will only match two or more consecutive empty lines replacing by an empty line.
My test code:
var lines = 'firstLine\n\n\n\nsecodLine\n\n\n\n\n\n\nthirdLine';
/*
firstLine
secondLine
thirdLine
*/
console.log(lines.replace(/([\r\n]){2,}/g, '\n\n'));
/*
firstLine
secodLine
thirdLine
*/
Try:
outputText = outputText.filter(function(e){
return e.replace(/[\r\n]+/g, '\n\n')});
I am not sure about the filter function above. but try below one must work.
outputText = outputText.replace(/[\r\n]+/g, '\n\n');
replacing with two new lines is the simplest way. you will get what you want.
I don't know if loadStrings leaves newlines at the end of the line or not. I'll assume it does (based on some code I see on this page). If it ends up mangled, please say so.
It is definitely easier to do this on a single string, like Hélio Márcio Filho says. So in your case, where you start with an array, you could just join the array together,replace three or more newlines with just two, then split it back up into lines:
let outputText = inputText.join('').replace(/(?:\r?\n){3,}/g, '\n\n').
split(/\n/).map(line => line + "\n");
But you can also do it just with filter - you just need to know how many empty lines you just saw, and suppress the extra ones:
let empties = 0;
let outputText = inputText.filter(line => {
if (line.replace(/[\r\n]+/, '')) empties = 0;
else empties++;
return empties <= 1;
});
The other answers work with a single string, but you're using the loadStrings() function from Processing.js, which gives you an array of strings.
You could convert the array into a single string, or load the file as a single string, but it seems simplest to me if you just process the array. Something like this:
function reduceNewlines(inputArray){
var outputNewArray = [];
var previousLineWasNewline = false;
for(var i = 0; i < myArray.length; i++){
if(myArray[i] == ''){
if(!previousLineWasNewline){
outputArray.push('');
}
previousLineWasNewline = true;
}
else{
outputArray.push(myArray[i]);
previousLineWasNewline = true;
}
}
return outputArray;
}
Please note that I haven't tested this code, and there is probably a ton of room for improvement. But the general idea is there: you could write a function that processed the array and returned a new array with the consecutive newlines removed.
You might also consider pre-processing your text file so you don't have to do this at all.
First of all, I would like to thank everyone for trying to help. I studied all your replies, I've tested each of them and they all work (some with needed tweaking) as stand-alone code, but when I inserted them into my code, some things went wrong. So I struggled and came out with my own solution, which is greatly inspired by your comments.
So the code that worked in my case is :
function reduceNewlines(outputTextEditNewLines) {
for (let key = 0; key < outputTextEditNewLines.length; key++) {
if (outputTextEditNewLines[key] == '') outputTextEditNewLines[key] = '\n';
else outputTextEditNewLines[key] = outputTextEditNewLines[key];
}
arrayToString = outputTextEditNewLines.join(""); // convert object myArray to string
console.log(arrayToString.replace(/([\r\n]){1,}/g, '\n\n')); // exports the text as it should
return arrayToString.replace(/([\r\n]){1,}/g, '\n\n');
}
The console.log exports the text as it should. Now the next step for my project is to make this string print to the DOM as it prints in the console.log.

console.log("this.length--->" + this.length); this behaviour

I am trying to learn js basics.
I tried analysing the string count code but I am not sure about certain statements.
can you guys tell me why it's behaving in such a way?
this will help to understand better and in future, I can fix the issues by myself.
providing code below
String.prototype.count=function(c) {
var result = 0;
var i = 0;
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
console.log("this.length--->" + this.length);
for(i;i<this.length;i++)
{
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
console.log("c--->" + c);
if(this[i]==c)
{
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
}
}
console.log("out of for loop result--->" + result);
// how its printing 4 but s is present only two times
return result;
//console.log("out of for loop result--->" + result);
};
console.log("strings".count("s")); //2
output
this--->strings
this.length--->7
this[i]--->s
c--->s
inside if result++ ---->1
this[i]--->t
c--->s
this[i]--->r
c--->s
this[i]--->i
c--->s
this[i]--->n
c--->s
this[i]--->g
c--->s
this[i]--->s
c--->s
inside if result++ ---->3
out of for loop result--->4
4
Questions from your code example are basicly about 2 issues:
this - is JS keyword. You don't have to initialize it, it automatically defined everytime, everywhere in your JS code. And it could mean different things in different situations, but it's too advanced topic if you've just started learning JS. For now lets just say, that this refers to the context, that called count() function, which is the string "strings". So it has length and you can iterate over it as an array of characters
Why the count rose to number 4, when it should be 2? Because when you found a match between current letter of the string and the character "s" (line with this[i]==c) you increment the result by 1 using result++. But you do it also in your console.log right after it, so it gets increased by 2 every time it finds a match
console.log("this--->" + this); // how come this prints strings here, since we dont pass stings here
That prints a string because you have a string + something. This is called string concatenation and the result of string concatenation is a string. In this case, this is the object that called the count function which was a string.
console.log("this[i]--->" + this[i]); // here we did not declare this an array anywhere right then how come its taking this[i] as s and stings also we did not put in any array
this is a string. Bracket notation on a string will return the char at the provided index.
result++;
console.log("inside if result++ ---->" + result++);
// here it prints 1 and 3 but only two times s is present so it should print 1 and 2 right
the result++ notation is the same as result += 1, but result++ does the addition of 1 AFTER the value is evaluated while ++result will do it before. So in this example the order of events is:
add 1 to the result, then print the console.log, then add 1 to the result
Hope that helps!

Javascript - using innerHTML to output strings *WITHOUT* HTML-encoded special characters?

It appears that JavaScript auto-converts certain special characters into HTML entities when outputting content via the innerHTML() function. This is a problem, since I need to be able to output < and > without converting to gt; and lt;
Can this auto-conversion be prevented, reversed, or escaped? So far, no matter what I do, < and > are always automatically encoded into HTML entities.
Example code:
function DisplayQueries() {
var IDs = ['AllOpenedINC','AllOpenedCRQ','AllClosedINC','AllClosedCRQ','SameDayINC','SameDayCRQ','NotSameDayINC','NotSameDayCRQ',
'StillOpenINC','StillOpenCRQ','OpenOldINC','OpenOldCRQ','OtherQueuesINC','OtherQueuesCRQ']
for (var i = 0; i < IDs.length; i++) {
if (eval(IDs[i]))
document.getElementById(IDs[i]).innerHTML = eval(IDs[i]);
}
}
Example query variable:
AllOpenedINC = "('Company*+' = \"test\" OR 'Summary*' = \"%test%\") AND ('Submit Date' >= \"" + theDate +
" 12:00:00 AM\" AND 'Submit Date' <= \"" + theDate + " 11:59:59 PM\")" + nameINC;
You should focus on what you want to accomplish as a result, rather than the way of doing it. innerHTML() does encode, innerText() and textContent() do encoding too. So you should decode your strings if you want them as < or > back.
You can use this unescapeHTML() function to get your results as you want them.
function unescapeHTML() {
return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');
}
I hope this helps. I've copied it from Prototype.
I think your question is based on a false premise. Just make a very simple test:
document.getElementById("testdiv").innerHTML = '<h1><em>Hello</em></h1>';
if this works fine then the problem is not on the JS side, instead you use some other components in your system which HTML-encode your characters.
I figured out what's going on. There's no easy way to prevent innerHTML from converting special characters to HTML entities, but since the problem was surfacing when copying the content of a DIV to the clipboard (using IE-only JS, which works since this is in a government environment where everyone has to use IE), I just used the replace() function to re-convert the HTML entities back to < and >.
You can use jquery and .append()

Categories