This is an example of the input:
var input="0-test-different-0_0:11,0-test-different-0_1:54,0-test-different-1_0:19,0-test-different-1_1:8,0-test-same-2_0:20,0-test-same-2_1:20,0-test-different-3_0:19,0-test-different-3_1:16,0-test-different-4_0:18,0-test-different-4_1:17,0-test-different-5_0:20,0-test-different-5_1:11,0-test-different-6_0:20,0-test-different-6_1:12,0-test-same-7_0:20,0-test-same-7_1:16,0-test-different-8_0:17,0-test-different-8_1:11,0-test-same-9_0:19,0-test-same-9_1:17,01-trial-same-10_0:19,01-trial-same-10_1:23,02-trial-different-11_0:22,02-trial-different-11_1:10,03-trial-different-12_0:20,03-trial-different-12_1:12,04-trial-same-13_0:18,04-trial-same-13_1:14,05-trial-same-14_0:17,05-trial-same-14_1:19,06-trial-different-15_0:21,06-trial-different-15_1:10,07-trial-same-16_0:20,07-trial-same-16_1:17,08-trial-different-17_0:20,08-trial-different-17_1:8,09-trial-same-18_0:20,09-trial-same-18_1:10,10-trial-different-19_0:21,10-trial-different-19_1:10,11-trial-same-20_0:19,11-trial-same-20_1:12,12-trial-same-21_0:19,12-trial-same-21_1:16,13-trial-different-22_0:19,13-trial-different-22_1:14,14-trial-different-23_0:22,14-trial-different-23_1:13,15-trial-same-24_0:19,15-trial-same-24_1:12,16-trial-same-25_0:18,16-trial-same-25_1:10,17-trial-different-26_0:20,17-trial-different-26_1:30,18-trial-different-27_0:21,18-trial-different-27_1:20,19-trial-same-28_0:17,19-trial-same-28_1:15,20-trial-different-29_0:17,20-trial-different-29_1:12,21-trial-different-30_0:18,21-trial-different-30_1:11,22-trial-different-31_0:16,22-trial-different-31_1:13,23-trial-same-32_0:19,23-trial-same-32_1:13,24-trial-different-33_0:19,24-trial-different-33_1:11,25-trial-same-34_0:20,25-trial-same-34_1:17,26-trial-same-35_0:22,26-trial-same-35_1:20,27-trial-same-36_0:20,27-trial-same-36_1:14,28-trial-same-37_0:22,28-trial-same-37_1:11,29-trial-different-38_0:19,29-trial-different-38_1:15,30-trial-same-39_0:19,30-trial-same-39_1:14,31-trial-different-40_0:18,31-trial-different-40_1:10,32-trial-different-41_0:18,32-trial-different-41_1:12-0-test-different-0_0:8,0-test-different-0_1:54,0-test-different-1_0:21,0-test-different-1_1:11,0-test-same-2_0:24,0-test-same-2_1:20,0-test-different-3_0:13,0-test-different-3_1:18,0-test-different-4_0:20,0-test-different-4_1:20,0-test-different-5_0:19,0-test-different-5_1:10,0-test-different-6_0:18,0-test-different-6_1:13,0-test-same-7_0:16,0-test-same-7_1:16,0-test-different-8_0:15,0-test-different-8_1:10,0-test-same-9_0:22,0-test-same-9_1:15,01-trial-same-10_0:20,01-trial-same-10_1:23,02-trial-different-11_0:24,02-trial-different-11_1:14,03-trial-different-12_0:18,03-trial-different-12_1:14,04-trial-same-13_0:18,04-trial-same-13_1:12,05-trial-same-14_0:23,05-trial-same-14_1:21,06-trial-different-15_0:21,06-trial-different-15_1:12,07-trial-same-16_0:19,07-trial-same-16_1:16,08-trial-different-17_0:22,08-trial-different-17_1:8,09-trial-same-18_0:21,09-trial-same-18_1:7,10-trial-different-19_0:16,10-trial-different-19_1:10,11-trial-same-20_0:21,11-trial-same-20_1:10,12-trial-same-21_0:18,12-trial-same-21_1:20,13-trial-different-22_0:19,13-trial-different-22_1:13,14-trial-different-23_0:17,14-trial-different-23_1:9,15-trial-same-24_0:19,15-trial-same-24_1:11,16-trial-same-25_0:23,16-trial-same-25_1:11,17-trial-different-26_0:21,17-trial-different-26_1:27,18-trial-different-27_0:20,18-trial-different-27_1:22,19-trial-same-28_0:19,19-trial-same-28_1:19,20-trial-different-29_0:21,20-trial-different-29_1:10,21-trial-different-30_0:19,21-trial-different-30_1:11,22-trial-different-31_0:20,22-trial-different-31_1:10,23-trial-same-32_0:21,23-trial-same-32_1:10,24-trial-different-33_0:19,24-trial-different-33_1:14,25-trial-same-34_0:16,25-trial-same-34_1:16,26-trial-same-35_0:22,26-trial-same-35_1:22,27-trial-same-36_0:23,27-trial-same-36_1:18,28-trial-same-37_0:19,28-trial-same-37_1:12,29-trial-different-38_0:21,29-trial-different-38_1:13,30-trial-same-39_0:22,30-trial-same-39_1:13,31-trial-different-40_0:21,31-trial-different-40_1:11,32-trial-different-41_0:19,32-trial-different-41_1:11";
At string index 2015 there is a - which actually separates this string in two.
It is different from all the other dashes in that it is the ONLY one preceeded by a colon (:) and then 1 to N numbers before there is a dash.
The way I've been finding it is by using this procedure:
var searchingColon = true;
for (var i = 0; i < input.length; i++){
if ((searchingColon) && (input.charAt(i) == ':')){
searchingColon = false;
}
else if (!searchingColon){
if (input.charAt(i) == "-"){
console.log("Found at " + i);
return;
}
if (isNaN(parseInt(input.charAt(i), 10))) {
searchingColon = true;
}
}
}
However it takes a while and I thought a regular expression would be better.
So I've tried this:
regex = "/:[0-9]+-/"
var res = input.search(regex)
console.log(res)
But res is -1, which mean it hasn't found anything. What am I doing wrong?
You should remove the quotes. Regular expressions in JavaScript are enclosed by forward slashes, not quotes.
regex = /:[0-9]+-/;
var res = input.search(regex)
console.log(res)
However, you can create a regex surround by quotes if you use the Regex constructor.
var regex2 = new RegExp(':[0-9]+-');
I usually prefer the first method, because you have to escape the \ and use \\ if you use the string variation.
I'm hoping someone can explain to me why I need to use "toLowerCase()" if I'm already using a regular expression that is case insensitive "i".
The exercise is a pangram that can accept numbers and non-ascii characters, but all letters of the alphabet MUST be present in lower case, upper case, or mixed. I wasn't able to solve this exercise correctly until I added "toLowerCase()". This is one of the javascript exercises from exercism.io. Below is my code:
var Pangram = function (sentence) {
this.sentence = sentence;
};
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
for (var i = 0; i < alphabet.length; i++){
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
};
module.exports = Pangram;
The regex may not be doing what you think it's doing. Here is your code commented with what's going on:
Pangram.prototype.isPangram = function (){
var alphabet = "abcdefghijklmnopqrstuvwxyz", mustHave = /^[a-z]+$/gi,
x = this.sentence.toLowerCase(), isItValid = mustHave.test(x);
// for every letter in the alphabet
for (var i = 0; i < alphabet.length; i++){
// check the following conditions:
// letter exists in the sentence (case sensitive)
// AND sentence contains at least one letter between a-z (start to finish, case insensitive)
if (x.indexOf(alphabet[i]) === -1 && isItValid === false){
return false;
}
}
return true;
}
The logic that is checking whether each letter is present has nothing to do with the regex, the two are serving separate purposes. In fact, based on your description of the problem, the regex will cause your solution to fail in some cases. For example, assume we have the string "abcdefghijklmnopqrstuvwxyz-". In that case your regex will test false even though this sentence should return true.
My advice would be to remove the regex, use toLowerCase on the sentence, and iterate through the alphabet checking if the sentence has each letter - which you seems to be the track you were on.
Below is a sample solution with some tests. Happy learning!
function isPangram (str) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const strChars = new Set(str.toLowerCase().split(''))
return alphabet.split('').every(char => strChars.has(char))
}
const tests = [
"abc",
"abcdefghijklmnopqrstuvwxyz",
"abcdefghijklmnopqRstuvwxyz",
"abcdefghijklmnopqRstuvwxyz-",
]
tests.forEach(test => {
console.log(test, isPangram(test))
})
It's because you're manually checking for lowercase letters:
if (x.indexOf(alphabet[i]) === -1)
alphabet[i] will be one of your alphabet string, which you have defined as lowercase.
It looks like you don't need the regex at all here, or at least it's not doing what you think it's doing. Since your regex only allows for alpha characters, it will fail if your sentence has any spaces.
I want to after type Title of post automatically take value and create slug. My code works fine with English Latin characters but problem is when I type characters 'čćšđž'. Code replace first type of this characters in string but if character is repeated than is a problem. So, for testing purpose this title 'šžđčćžđš čćšđžčćšđž čćšđžčć ćčšđžšžčćšđ ćčšžčć' is converted to this slug 'szdcc'.
This is my jquery code:
$('input[name=title]').on('blur', function() {
var slugElement = $('input[name=slug]');
if(slugElement.val()) {
return;
}
slugElement.val(this.value.toLowerCase().replace('ž', 'z').replace('č','c').replace('š', 's').replace('ć', 'c').replace('đ', 'd').replace(/[^a-z0-9-]+/g, '-').replace(/^-+|-+$/g, ''));
});
How to solve this problems? Also is it possible to this few characters put in same replace() function?
Try this:
function clearText(inp) {
var wrong = 'čćšđž';
var right = 'ccsdz';
var re = new RegExp('[' + wrong + ']', 'ig');
return inp.replace(re, function (m) { return right.charAt(wrong.indexOf(m)); });
}
replace() only replaces the first occurrence unless regex is used with global modifier. You will need to change them all to regular expression.
replace(/ž/g, "z")
As far as I know, it will not be possible to use a single replace() in your case.
If you are concerned with chaining a bunch of .replace() together, you might be better off writing some custom code to replace these characters.
var newStr = "";
for (var i = 0; i < str.length; i++) {
var c = str.charAt(i);
switch (c) {
case "ž": newStr += "z"; break;
default: newStr += c; break;
}
}
Can anyone tell me why does this not work for integers but works for characters? I really hate reg expressions since they are cryptic but will if I have too. Also I want to include the "-()" as well in the valid characters.
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
Review
String.prototype.Contains = function (str) {
return this.indexOf(str) != -1;
};
This String "method" returns true if str is contained within itself, e.g. 'hello world'.indexOf('world') != -1would returntrue`.
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
The value of $('#textbox1').val() is already a string, so the .toString() isn't necessary here.
if (str.Contains(validChars)) {
alert("found");
} else {
alert("not found");
}
This is where it goes wrong; effectively, this executes '1234'.indexOf('0123456789') != -1; it will almost always return false unless you have a huge number like 10123456789.
What you could have done is test each character in str whether they're contained inside '0123456789', e.g. '0123456789'.indexOf(c) != -1 where c is a character in str. It can be done a lot easier though.
Solution
I know you don't like regular expressions, but they're pretty useful in these cases:
if ($("#textbox1").val().match(/^[0-9()]+$/)) {
alert("valid");
} else {
alert("not valid");
}
Explanation
[0-9()] is a character class, comprising the range 0-9 which is short for 0123456789 and the parentheses ().
[0-9()]+ matches at least one character that matches the above character class.
^[0-9()]+$ matches strings for which ALL characters match the character class; ^ and $ match the beginning and end of the string, respectively.
In the end, the whole expression is padded on both sides with /, which is the regular expression delimiter. It's short for new RegExp('^[0-9()]+$').
Assuming you are looking for a function to validate your input, considering a validChars parameter:
String.prototype.validate = function (validChars) {
var mychar;
for(var i=0; i < this.length; i++) {
if(validChars.indexOf(this[i]) == -1) { // Loop through all characters of your string.
return false; // Return false if the current character is not found in 'validChars' string.
}
}
return true;
};
var validChars = '0123456789';
var str = $("#textbox1").val().toString();
if (str.validate(validChars)) {
alert("Only valid characters were found! String validates!");
} else {
alert("Invalid Char found! String doesn't validate.");
}
However, This is quite a load of code for a string validation. I'd recommend looking into regexes, instead. (Jack's got a nice answer up here)
You are passing the entire list of validChars to indexOf(). You need to loop through the characters and check them one-by-one.
Demo
String.prototype.Contains = function (str) {
var mychar;
for(var i=0; i<str.length; i++)
{
mychar = this.substr(i, 1);
if(str.indexOf(mychar) == -1)
{
return false;
}
}
return this.length > 0;
};
To use this on integers, you can convert the integer to a string with String(), like this:
var myint = 33; // define integer
var strTest = String(myint); // convert to string
console.log(strTest.Contains("0123456789")); // validate against chars
I'm only guessing, but it looks like you are trying to check a phone number. One of the simple ways to change your function is to check string value with RegExp.
String.prototype.Contains = function(str) {
var reg = new RegExp("^[" + str +"]+$");
return reg.test(this);
};
But it does not check the sequence of symbols in string.
Checking phone number is more complicated, so RegExp is a good way to do this (even if you do not like it). It can look like:
String.prototype.ContainsPhone = function() {
var reg = new RegExp("^\\([0-9]{3}\\)[0-9]{3}-[0-9]{2}-[0-9]{2}$");
return reg.test(this);
};
This variant will check phones like "(123)456-78-90". It not only checks for a list of characters, but also checks their sequence in string.
Thank you all for your answers! Looks like I'll use regular expressions. I've tried all those solutions but really wanted to be able to pass in a string of validChars but instead I'll pass in a regex..
This works for words, letters, but not integers. I wanted to know why it doesn't work for integers. I wanted to be able to mimic the FilteredTextBoxExtender from the ajax control toolkit in MVC by using a custom Attribute on a textBox
Struggling with a regex requirement. I need to split a string into an array wherever it finds a forward slash. But not if the forward slash is preceded by an escape.
Eg, if I have this string:
hello/world
I would like it to be split into an array like so:
arrayName[0] = hello
arrayName[1] = world
And if I have this string:
hello/wo\/rld
I would like it to be split into an array like so:
arrayName[0] = hello
arrayName[1] = wo/rld
Any ideas?
I wouldn't use split() for this job. It's much easier to match the path components themselves, rather than the delimiters. For example:
var subject = 'hello/wo\\/rld';
var regex = /(?:[^\/\\]+|\\.)+/g;
var matched = null;
while (matched = regex.exec(subject)) {
print(matched[0]);
}
output:
hello
wo\/rld
test it at ideone.com
The following is a little long-winded but will work, and avoids the problem with IE's broken split implementation by not using a regular expression.
function splitPath(str) {
var rawParts = str.split("/"), parts = [];
for (var i = 0, len = rawParts.length, part; i < len; ++i) {
part = "";
while (rawParts[i].slice(-1) == "\\") {
part += rawParts[i++].slice(0, -1) + "/";
}
parts.push(part + rawParts[i]);
}
return parts;
}
var str = "hello/world\\/foo/bar";
alert( splitPath(str).join(",") );
Here's a way adapted from the techniques in this blog post:
var str = "Testing/one\\/two\\/three";
var result = str.replace(/(\\)?\//g, function($0, $1){
return $1 ? '/' : '[****]';
}).split('[****]');
Live example
Given:
Testing/one\/two\/three
The result is:
[0]: Testing
[1]: one/two/three
That first uses the simple "fake" lookbehind to replace / with [****] and to replace \/ with /, then splits on the [****] value. (Obviously, replace [****] with anything that won't be in the string.)
/*
If you are getting your string from an ajax response or a data base query,
that is, the string has not been interpreted by javascript,
you can match character sequences that either have no slash or have escaped slashes.
If you are defining the string in a script, escape the escapes and strip them after the match.
*/
var s='hello/wor\\/ld';
s=s.match(/(([^\/]*(\\\/)+)([^\/]*)+|([^\/]+))/g) || [s];
alert(s.join('\n'))
s.join('\n').replace(/\\/g,'')
/* returned value: (String)
hello
wor/ld
*/
Here's an example at rubular.com
For short code, you can use reverse to simulate negative lookbehind
function reverse(s){
return s.split('').reverse().join('');
}
var parts = reverse(myString).split(/[/](?!\\(?:\\\\)*(?:[^\\]|$))/g).reverse();
for (var i = parts.length; --i >= 0;) { parts[i] = reverse(parts[i]); }
but to be efficient, it's probably better to split on /[/]/ and then walk the array and rejoin elements that have an escape at the end.
Something like this may take care of it for you.
var str = "/hello/wo\\/rld/";
var split = str.replace(/^\/|\\?\/|\/$/g, function(match) {
if (match.indexOf('\\') == -1) {
return '\x00';
}
return match;
}).split('\x00');
alert(split);