I have a string which needs to be split by three underscore characters. An example of the string might be:
var stringItemsPlanner = "Hello this___is a string___which___needs splitting into___an array";
So I use the Split() function. Fine in everything but IE8 (and probably 7 too but not tried) which gives an "Object doesn't support this property or method" error if the string doesn't contain those characters. So I found another post which said to check that the underscore characters appear in the string before splitting, so I do this:
if (stringItemsPlanner.indexOf('___') == -1){
arrItemsPlanner = [];
}else{
arrItemsPlanner = stringItemsPlanner.split('___');
}
But now this errors too because apparently IE8 doesn't support 'indexOf'.
After a lot of searching I've tried adding some code to the top of my script to act as a 'polyfil' for this method:
if (!Array.prototype.indexOf){
Array.prototype.indexOf = function(elt /*, from*/){
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)? Math.ceil(from) : Math.floor(from);
if (from < 0){
from += len;
for (; from < len; from++){
if (from in this && this[from] === elt){
return from;
}
return -1;
};
}
}
}
But still no joy.
I'm now past the point of frustration and can't really think of any other way to get this simple thing to work.
Can anyone shed any light on this or think of an alternative way to safely split a string to an array in a way that works cross-browser? It's got to be simple but I just can't think straight now.
Thanks all!
Have a look here
http://jsfiddle.net/mplungjan/Bnx6m/
var stringItemsPlanner = "Hello this___is a string___which___needs splitting into___an array";
var arrItemsPlanner = (stringItemsPlanner.length==0 || stringItemsPlanner.indexOf('___') == -1)? []:stringItemsPlanner.split('___');
alert(arrItemsPlanner.join('\n'))
Related
"Write a JavaScript function to find longest substring in a given a string without repeating characters."
Here's what I tried, but it doesn't print anything
function sort(names) {
let string = "";
let namestring = names.split("");
for(let i = 0; i < namestring.length; i++) {
for(let j = 0; j < string.length; j++) {
if(string[j] != namestring[i]) {
string = string + namestring[i];
}
}
}
return string;
}
console.log(sort("google.com"));
What's wrong?
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i]))
break;
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
It's o(n^2) complexity but try this(may be o(n^3) if contains function take o(n) complexity)
function sort(names)
{
string="";
ss="";
namestring=names.split("");
for(j=0;j<namestring.length;j++) {
for(i=j;i<namestring.length;i++) {
if(string.includes(namestring[i])) // if contains not work then
break; //use includes like in snippet
else
string+=namestring[i];
}
if(ss.length<string.length)
ss=string;
string="";
}
return ss;
}
console.log(sort("google.com"));
What are you expecting the answer to be here? Should it be "ogle.com" or "gle.com"? If the first, the below should get you there, if the latter, update the tested = name.charAt(i) in the else to tested = "".
So a few things to note, though you're more than welcome to do as you wish:
1) the function name. This isn't doing a "sort" as far as I can tell, so if this is for your use (or any reuse. Basically, anything more than a one off homework assignment), you may want to rename it to something you'd actually remember (even the example I give is probably not completely best as "pick longest substring" is non-descriptive criteria).
2) variable naming. string and namestring may mean something to you here, but considering we're trying to find the longest substring (with the no double characters) in a string, I felt it was better to have the one we're checking against (tested) and the one we're storing to return later (longest). It helps make sense as you're reading through the code as you know when you are done with a checked string (tested), you want to compare if it is greater than the current longest substring (longest) and if it is bigger, you want it to be the new longest. This will save you a ton of headache to name variables to things that'll help when designing your function as you can get it as close to requirements written down as possible without trying to do some form of substitution or worse, forgetting which variable holds what.
I don't know what you want the result to be in the event that tested length is the same as longest length. Currently I have it set to retain, if you want the most recent, update the check to >=.
Beyond that, I just iterate over the string, setting to the currently tested string. Once double characters are met, I then see if what I just generated (tested) is larger than the current longest and if it is, it is now the longest. Once I finish looping across the string, I have to do the current vs longest check/set again as otherwise, it'd make the final tested meaningless (it went outside the loop before another double character situation was hit).
function pickLongestSubstring(name) {
let tested = "";
let longest = "";
for (let i = 0; i < name.length; i++) {
if (tested.length == 0 || tested.charAt(tested.length - 1) != name.charAt(i)) {
tested += name.charAt(i);
}
else {
if (tested.length > longest.length) {
longest = tested;
tested = "";
}
}
}
if (tested.length > longest.length) {
longest = tested;
}
return longest;
}
console.log(pickLongestSubstring("google.com"))
console.log(pickLongestSubstring("example.com"))
This is a recursive loop that should get the longest string. Uses sort to determine longest string. Works, even if multiple instances of same repeat char.
function longestWithoutRepeat(testString, returnString){
var returnString = returnString || "";
for(var i = 0; i < testString.length; i++) {
if(i > 0){
if(testString[i] == testString[i-1]) {
var testStringArray = testString.split(testString[i] + testString[i-1]);
testStringArray.sort(function(firstString, nextString){ return nextString.length - firstString.length})
returnString = testStringArray[0];
longestWithoutRepeat(testStringArray[0], returnString);
}
} else {
returnString = testString
}
}
return returnString;
}
console.log(longestWithoutRepeat("oolong"));
console.log(longestWithoutRepeat("google.com"));
console.log(longestWithoutRepeat("diddlyougotoofarout"));
First of all: I'm a bit into JavaScript but not much.
Today I saw these code:
if (stringToSearch[i].charCodeAt(0) === codeToSearch) {
The charCodeAt() method of String is used for to compare the current char with the searched char.
The full code of the function here:
function getOccurences (stringToSearch, charToSearch) {
var ret = 0;
var codeToSearch = 0;
var i;
stringToSearch = stringToSearch.toUpperCase();
codeToSearch = charToSearch.toUpperCase().charCodeAt(0);
for (i = 0; i < stringToSearch.length; i++) {
if (stringToSearch[i].charCodeAt(0) === codeToSearch) {
ret++;
}
}
return ret;
}
I would have compared the char directly. Without using charCodeAt().
Just ...
stringToSearch[i] === charToSeach
As far as I know the computer compares just numbers anyway. Translates the characters to their UTF-codes. Subtracts these numbers against each other and then checks if the result has become zero.
So therefore my question:
Does the usage of charCodeAt() makes any sense?
Are there a benefit to favor the direct charCode-comparison over the character-comparison.
My intuition is to say there's a performance hit when you go through type-conversion and function-calling hoops like that.
That said, you'll likely eke out more performance out of the code by delegating to the native string methods, with something like:
function countCaseInsensitiveOccurrences(haystack, char) {
haystack = haystack.toUpperCase();
char = char.toUpperCase()[0];
var count = 0, pos = -1;
while ((pos = haystack.indexOf(char, pos + 1)) !== -1) {
count++;
}
return count;
}
charCode benefits when we have to increment/decrement the characters.
eg. if we have charCode('a') in variable x, then we can increment it using x++.
But if we had saved 'a' then we cannot perform arithmetic operations.
So charCodeAt(number) is used when you need to increment/decrement the characters.
I'm totally not a Math whiz kid here, but have put together a function with the great help of StackOverflow (and a lot of trial and error) that generates a random serial number from a Formula, group of Letters/Numbers, and array (so as to not duplicate values).
So, my current formula is as follows:
$.extend({
generateSerial: function(formula, chrs, checks) {
var formula = formula && formula != "" ? formula : 'XXX-XXX-XXX-XXX-XXX', // Default Formula to use, should change to what's most commonly used!
chrs = chrs && chrs != "" ? chrs : "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", // Default characters to randomize, if not defined!
len = (formula.match(/X/g) || []).length,
indices = [],
rand;
// Get all "-" char indexes
for(var i=0; i < formula.length; i++) {
if (formula[i] === "-") indices.push(i);
}
do {
rand = Array(len).join().split(',').map(function() {
return chrs.charAt(Math.floor(Math.random() * chrs.length));
}).join('');
// Rebuild string!
if (indices && indices.length > 0)
{
for(var x=0; x < indices.length; x++)
rand = rand.insert(indices[x], '-');
}
} while (checks && $.inArray(rand, checks) !== -1);
return rand;
}
});
Ok, so, what I need to be able to do is to find total possible values and make sure that it is possible to generate a unique serial number before actually doing so.
For example:
var num = $.generateSerial('XX', 'AB', new Array('AB', 'BA', 'AA', 'BB'));
This will cause the code to do an infinite loop, since there are no more possibilties here, other than the ones being excluded from the extension. So this will cause browser to crash. What I need to be able to do here is to be able to get the number of possible unique values here and if it is greater than 0, continue, otherwise, don't continue, maybe an alert for an error would be fine.
Also, keep in mind, could also do this in a loop so as to not repeat serials already generated:
var currSerials = [];
for (var x = 0; x < 5; x++)
{
var output = $.generateSerial('XXX-XXX-XXX', '0123456789', currSerials);
currSerials.push(output);
}
But the important thing here, is how to get total possible unique values from within the generateSerial function itself? We have the length, characters, and exclusions array also in here (checks). This would seem more like a math question, and I'm not expert in Math. Could use some help here.
Thanks guys :)
Here is a jsFiddle of it working nicely because there are more possible choices than 16: http://jsfiddle.net/qpw66bwb/1/
And here is a jsFiddle of the problem I am facing: Just click the "Generate Serials" button to see the problem (it continuously loops, never finishes), it wants to create 16 serials, but 16 possible choices are not even possible with 2 characters and only using A and B characters: http://jsfiddle.net/qpw66bwb/2/
I need to catch the loop here and exit out of it, if it is not able to generate a random number somehow. But how?
The number of possible serials is len * chrs.length, assuming all the characters in chrs are different. The serial contains len characters to fill in randomly, and chrs.length is the number of possible characters in each position of that.
After splitting a set of glossary terms with:
lines = text.split(/[\r\n]+/);
I then iterate through the array and parse out each term to properly format them during output. However, a simple check for empty strings has become much more of a headache than I could've ever imagined. Console logging gives me this:
...
"Pushing" "dyspnea: Labored or difficult respiration." //correct
"Pushing" ""
...
Things I have tried in order to find these empty strings:
line === ""
line.length == 0
if(line)
isNaN(line.charCodeAt(0))
typeof line == "undefined"
And various combinations of the list above. On recommendation from a coworker, I checked the line endings of the input text, but it all seemed normal.
I'm sure I'm just doing something really stupid, but the solution has eluded me for far too long. Any help/suggestions would be greatly appreciated!
Edit:
Thanks for the suggestions everyone. Alas, the problem persists...
Also, I forgot to mention, but I have tried both trimming and replacing whitespace in each line after the split, but came up with nothing.
As requested, here is more relevant code.
var text = "";
var end = /\x2E\s\x5B/gm; // ". ["
var lines = [];
var terms = [];
text = document.getElementById("terms").value;
lines = text.split(/[\r\n]+/);
parseText();
function parseText() {
var i = 0;
while(i < lines.length) {
var line = lines[i];
endIndex = lines[i].search(end);
if(line != "" || line != " " || line.length != 0 ) {
parseTerm(lines[i].substring(0, endIndex+1));
}
i++;
}
As the previous answer stated issue is probably whitespace, you can use the trim function to shorten your code:
if (line.trim() == "") {
alert("Blank");
}
maybe string is not a "", but " "?
so check not only zero length, but "white space"
if(st1 == "" || st1 == " " || st1.length == 0 ){
console.log("find empty")
}
Turns out that in my input there was a line with two spaces. I have NO idea why this was causing problems, considering the split was specifically on the pattern described above, but replacing instances of too much whitespace fixed the issue. The new line:
text.replace(/\s\s+/g, " ").split(/[\r\n]+/);
what is the easiest way to figure out if a string ends with a certain value?
you could use Regexps, like this:
str.match(/value$/)
which would return true if the string has 'value' at the end of it ($).
Stolen from prototypejs:
String.prototype.endsWith = function(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
'slaughter'.endsWith('laughter');
// -> true
Regular expressions
"Hello world".match(/world$/)
I had no luck with the match approach, but this worked:
If you have the string, "This is my string." and wanted to see if it ends with a period, do this:
var myString = "This is my string.";
var stringCheck = ".";
var foundIt = (myString.lastIndexOf(stringCheck) === myString.length - stringCheck.length) > 0;
alert(foundIt);
You can change the variable stringCheck to be any string to check for. Better still would be to throw this in your own function like this:
function DoesStringEndWith(myString, stringCheck)
{
var foundIt = (myString.lastIndexOf(stringCheck) === myString.length - stringCheck.length) > 0;
return foundIt;
}
You can do 'hello world'.slice(-5)==='world'. Works in all browsers. Much faster than regex.
ES6 supports this directly:
'this is dog'.endsWith('dog') //true
I am just expanding on what #luca-matteis has posted but to solve the issues pointed out in the comments the code should be wrapped to make sure you are not overwriting a native implementation.
if ( !String.prototype.endsWith ) {
String.prototype.endsWith = function(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
}
This is the suggested method for the Array.prototype.forEach method pointed out in the mozilla developer network
You can always prototype String class, this will work:
String.prototype.endsWith = function(str)
{return (this.match(str+"$")==str)}
You can find other related extensions for String class in http://www.tek-tips.com/faqs.cfm?fid=6620