I am writing a HTML/JS bingo game. It needs to have functionality that lets users specify their own bingo board by entering a string that needs to be validated using a regex. The specifications are as follows:
The string format will be
B(15,9,8,7,14)I(25,21,20,22,29)N(38,41,f,34,31)G(60,57,48,56,49)O(69,70,72,64,71)
where B(15,9,8,7,14) means that the B column on the board contains
15, 9, 8, 7, and 14. I(25,21,20,22,29) means the I column contains
25, 21, 20, 22 and 29. And so forth. 'f' is used in the string to
represent the free space.
So far I have:
var string = /(B|b)(((1[0-5]|[1-9]),?){5})(I|i)(((1[6-9]|2[0-9]|30),?){5})(N|n)(((3[1-9]|4[0-5]),){2}(F|f),((3[1-9]|4[0-5]),?){2})(G|g)(((4[6-9]|5[0-9]|60),?){5})(O|o)(((6[1-9]|7[0-5]),?){5})/g;
Which validates the above example but doesn't check for duplicates. I.e., B(15,15,8,7,14)... should fail. I think negative lookahead is the right tool to use but i'm unsure how to use it in this context
Extract numbers from string into an Array, and check for duplicates:
var bingoStrings = [
"B(15,9,8,7,14)I(25,21,20,22,29)N(38,41,f,34,31)G(60,57,48,56,49)O(69,70,72,64,71)",
"B(15,15,8,7,14)I(25,21,20,22,29)N(38,41,f,34,31)G(60,57,48,56,49)O(69,70,72,64,71)"
];
bingoStrings.forEach(bingoString => {
var bingoArray = bingoString.match(/\d+/g);
var hasDuplicates = bingoArray.some(number =>
bingoArray.indexOf(number) !== bingoArray.lastIndexOf(number)
);
console.log(bingoString);
console.log("has " + (hasDuplicates?"":"no ") + "duplicates\n");
});
As a function:
var bingoStrings = [
"B(15,9,8,7,14)I(25,21,20,22,29)N(38,41,f,34,31)G(60,57,48,56,49)O(69,70,72,64,71)",
"B(15,15,8,7,14)I(25,21,20,22,29)N(38,41,f,34,31)G(60,57,48,56,49)O(69,70,72,64,71)"
];
hasDuplicates = (bingoString) =>
bingoString
.match(/\d+/g)
.some((number, index, bingoArray) =>
bingoArray.indexOf(number) !== bingoArray.lastIndexOf(number)
)
;
bingoStrings.forEach(bingoString => {
console.log(bingoString);
console.log("has " + (hasDuplicates(bingoString)?"":"no ") + "duplicates\n");
});
Related
I was wondering how to trim a file name in JS to show "..." or any appendix for that matter after a certain number of characters, the most efficient way to handle all possible test cases.
Rules
Show the actual file extension and not the last character after splitting the string name with "."
The function should take the input file name (string), the number of characters to trim (integer) and appendix (string) as the parameter.
By efficient, I mean I expect to write fewer lines of code and handle all possible edge cases.
Sample Inputs
myAwesomeFile.min.css
my Awesome File.tar.gz
file.png
Expected output (say I want to trim after 5 characters)
myAwe....min.css
my Aw....tar.gz
file.png
Editing the question to show my attempt
function trimFileName(str, noOfChars, appendix) {
let nameArray = str.split(".");
let fileType = `.${nameArray.pop()}`;
let fileName = nameArray.join(" ");
if (fileName.length >= noOfChars) {
fileName = fileName.substr(0, noOfChars) + appendix;
};
return (fileName + fileType);
}
console.log(trimFileName("myAwesomeFile.min.css", 5, "..."));
console.log(trimFileName("my Awesome File.tar.gz", 5, "..."));
console.log(trimFileName("file.png", 5, "..."));
Edit #2: Feel free to go ahead and edit the question if you think it's not the standard expectation and add more edge cases to the sample inputs and expected outputs.
Edit #3: Added a few more details to the question after the new comments. I know my attempt doesn't fulfill my expected outputs (and I am unsure whether the output I have listed above is a standard expectation or not).
Edit #4 (Final): Removed the rule of not breaking a word in the middle after a continuous backlash in the comments and changed the rules to cater to more realistic and practical use cases.
If we treat the dot character . as a separator for file extensions, what you ask for can be solved with a single line of JavaScript:
name.replace(new RegExp('(^[^\\.]{' + chars + '})[^\\.]+'), '$1' + subst);
Demo code in the following snippet:
function f(name, chars, subst) {
return name.replace(
new RegExp('(^[^\\.]{' + chars + '})[^\\.]+'), '$1' + subst);
}
test('myAwesomeFile.min.css', 5, '...', 'myAwe....min.css');
test('my Awesome File.tar.gz', 5, '...', 'my Aw....tar.gz');
test('file.png', 5, '...', 'file.png');
function test(filename, length, subst, expected) {
let actual = f(filename, length, subst);
console.log(actual, actual === expected ? 'OK' : 'expected: ' + expected);
}
On Windows, AFAIK, the file extension is only what follows the last dot. Thus, technically, the file extension of "myAwesomeFile.min.css" is just css, and the file extension of "my Awesome File.tar.gz" is just gz.
In this case, what you ask for can still be solved with one line of JavaScript:
name.replace(new RegExp('(^.{' + chars + '}).+(\\.[^\\.]*$)'), '$1' + subst + '$2');
Demo code in the following snippet:
function f(name, chars, subst) {
return name.replace(
new RegExp('(^.{' + chars + '}).+(\\.[^\\.]*$)'), '$1' + subst + '$2');
}
test('myAwesomeFile.min.css', 5, '...', 'myAwe....css');
test('my Awesome File.tar.gz', 5, '...', 'my Aw....gz');
test('file.png', 5, '...', 'file.png');
function test(filename, length, subst, expected) {
let actual = f(filename, length, subst);
console.log(actual, actual === expected ? 'OK' : 'expected: ' + expected);
}
If you really want to allow edge cases with specific multiple extensions, you probably need to define a comprehensive list of all allowed multiple extensions to know how to deal with cases like "my.awesome.file.min.css". You would need to provide a list of all cases you want to include before it would be possible to determine how efficient any solution could be.
It is really hard to account for all extensions (including edge cases). See this list for example for common extensions: https://www.computerhope.com/issues/ch001789.htm. Event with that many extensions, the list is exhaustive of all extensions.
Your function is OK but to account for more cases it could be re-written to this:
function trimFileName(filename, limit = 5, spacer = '.') {
const split = filename.indexOf(".");
const name = filename.substring(0, split);
const ext = filename.substring(split);
let trimName = name.substring(0, limit);
if (name.length > trimName.length)
trimName = trimName.padEnd(limit + 3, spacer);
return trimName + ext;
}
console.log(trimFileName("myAwesomeFile.min.css"));
console.log(trimFileName("my Awesome File.tar.gz"));
console.log(trimFileName("file.png"));
Below is a pretty simple approach to achieve shortening in the fashion you desire. Comments are in the code, but let me know if anything needs additional explanation:
//A simple object to hold some configs about how we want to shorten the file names
const config = {
charsBeforeTrim: 5,
seperator: '.',
replacementText: '....'
};
//Given file names to shorten
const files = ['myAwesomeFile.min.css', 'my Awesome File.tar.gz', 'file.png'];
//Function to do the actual file name shortening
const shorten = s =>
s.length > config.charsBeforeTrim ? `${s.substring(0, config.charsBeforeTrim)}${config.replacementText}` : s;
//Function to generate a short file name with extension(s)
const generateShortName = (file, config) => {
//ES6 Array destructuring makes it easy to get the file name in a unique variable while keeping the remaining elements (the extensions) in their own array:
const [name, ...extensions] = file.split(config.seperator);
//Simply append all remaining extension chunks to the shortName
return extensions.reduce((accum, extension) => {
accum += `${config.seperator}${extension}`;
return accum;
}, shorten(name));
};
//Demonstrate usage
const shortFileNames = files.map(file => generateShortName(file, config));
console.log(shortFileNames);
const parse = (filename, extIdx = filename.lastIndexOf('.')) => ({
name: filename.substring(0, extIdx),
extension: filename.substring(extIdx + 1),
})
const trimFileName = (
filename, size = 5, fill = '...',
file = parse(filename),
head = file.name.substring(0, size)
) => file.name.length >= size ? `${head}${fill}${file.extension}` : filename
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
;[
'myAwesomeFile.min.css',
'my.Awesome.File.min.css',
'my Awesome File.tar.gz',
'file.png',
].forEach(f => console.log(trimFileName(f)))
You can fairly straightforwardly pull the your extension condition (easily replaced with a list of valid extensions) and regex pull the last part. Then you just add a check on the filename (starting at the beginning of filename) to trim the result.
const trim = (string, x) => {
// We assume that up to last two . delimited substrings of length are the extension
const extensionRegex = /(?:(\.[a-zA-Z0-9]+){0,2})$/g;
const { index } = extensionRegex.exec(string);
// No point in trimming since result string would be longer than input
if (index + 2 < x) {
return string;
}
return string.substr(0, x) + ".." + string.substr(index);
};
/* Assert that we keep the extension */
console.log("cat.tar.gz", trim("cat.tar.gz", 100) == "cat.tar.gz");
console.log("cat.zip", trim("cat.zip", 100) == "cat.zip");
/* Assert that we keep x characters before trim */
console.log("1234567890cat.tar.gz",!trim("1234567890cat.tar.gz",10).includes("cat"));
console.log("1234567890cat.zip", !trim("1234567890cat.zip", 10).includes("cat"));
I have an ASCII character string and I need to convert it to a normal string.
var asciiString = '84114117116104326510811997121115328710511011532'
function strFunc(str) {
var result = []
var strSplit = str.split('');
var validAscii = ['32'];
for(var i=65; i<=90; i++) {
validAscii.push(i.toString());
}
for(var i=97; i<=122; i++) {
validAscii.push(i.toString());
}
strSplit.forEach((item, index) => {
if(validAscii.includes(parseInt(item))) {
result.push(item)
} else if (validAscii.includes(`${parseInt(strSplit[index])}${parseInt(strSplit[index + 1])}`)){
result.push(item)
}
})
return result.fromCharCodeAt(...result)
}
console.log(strFunc(asciiString))
Why does it return an empty string? I need to split the string into either 2 digit or 3 digits and compare it with the array I built.
The string should be split as [84, 114, 117, 116, 104, 32, 65, ...] which translates to TRUTH A....
Please advice.
I'd do this way
const encodedString = '84114117116104326510811997121115328710511011532';
const codes = [];
for (let i = 0; i < encodedString.length;) {
const numDigits = encodedString[i] === '1' ? 3 : 2;
codes.push(encodedString.substr(i, numDigits));
i += numDigits;
}
const str = String.fromCharCode(...codes);
console.log(`"${str}"`);
Some notes:
It assume values in the encoded string go from 32 to 127. There's no error checking
There's no reason to call parseInt as JavaScript will convert numbers strings to numbers so passing the numbers as strings to String.fromCharCode works.
As for why your code doesn't work, a couple of issues include
it's looping over every character, not every code.
It's looping over 8, 4, 1, 1, 4, ... instead of 84, 114, ...
This means neither test will pass since item will never be something found in validAscii which means result will have nothing pushed to it.
There's no function Array.fromCharCodeAt
result is an array and there is no such function as array.fromCharCodeAt. If result had the correct codes in it then you could use String.fromCharCode(...result)
When you're combining two elements of the string, you need to call parseInt() *on the result of the concatenation, not concatenate the results of parseInt(). So it should be:
} else if (validAscii.includes(parseInt(item + strSplit[index+1]))){
And since ASCII values can be 3 digits, you need another else if that looks for item + strSplit[index+1] + strSplit[index+2].
Another problem is that you're pushing item onto the result string. But to get the corresponding character, you need to use String.fromCharCode() to convert the concatenated ASCII code to a character.
strSplit.forEach((item, index) => {
if (validAscii.includes(parseInt(item))) {
result.push(String.fromCharCode(item))
} else if (validAscii.includes(parseInt(item + strSplit[index+1]))) {
result.push(String.fromCharCode(parseInt(item + strSplit[index+1]))
} else if (validAscii.includes(parseInt(item + strSplit[index+1] + strSplit[index+2]))) {
result.push(String.fromCharCode(parseInt(item + strSplit[index+1] + strSplit[index+2]))
}
})
Note that using forEach like this is probably not a good idea. If there are overlapping items in the input that are both in validAscii, you'll add both of them to the result. E.g. if it contains 678 you'll match both 67 and 78, and add the corresponding characters to the result. Instead, you should use an ordinaryfor` loop, and increment the index by the number of characters that you matched.
You want parseInt around the templated string, not the individual items. You were checking if the string is included in an array filled with numbers.
var asciiString = '84114117116104326510811997121115328710511011532'
function strFunc(str) {
var result = []
var strSplit = str.split('');
var validAscii = [32];
for(var i=65; i<=90; i++) {
validAscii.push(i);
}
for(var i=97; i<=122; i++) {
validAscii.push(i);
}
strSplit.forEach((item, index) => {
if(validAscii.includes(parseInt(item))) {
result.push(item)
} else if (validAscii.includes(parseInt(`${(strSplit[index])}${(strSplit[index + 1])}`))){
result.push(item);
}
})
return result.join('');
}
console.log(strFunc(asciiString))
Assume there are some strings containing names in different format (each line is a possible user input):
'Guilcher, G.M., Harvey, M. & Hand, J.P.'
'Ri Liesner, Peter Tom Collins, Michael Richards'
'Manco-Johnson M, Santagostino E, Ljung R.'
I need to transform those names to get the format Lastname ABC. So each surename should be transformed to its initial which are appended to the lastname.
The example should result in
Guilcher GM, Harvey M, Hand JP
Liesner R, Collins PT, Richards M
Manco-Johnson M, Santagostino E, Ljung R
The problem is the different (possible) input format. I think my attempts are not very smart, so I'm asking for
Some hints to optimize the transformation code
How do I put those in a single function at all? I think first of all I have to test which format the string has...??
So let me explain how far I tried to solve that:
First example string
In the first example there are initials followed by a dot. The dots should be removed and the comma between the name and the initals should be removed.
firstString
.replace('.', '')
.replace(' &', ', ')
I think I do need an regex to get the comma after the name and before the initials.
Second example string
In the second example the name should be splitted by space and the last element is handled as lastname:
const elm = secondString.split(/\s+/)
const lastname = elm[elm.length - 1]
const initials = elm.map((n,i) => {
if (i !== elm.length - 1) return capitalizeFirstLetter(n)
})
return lastname + ' ' + initals.join('')
...not very elegant
Third example string
The third example has the already the correct format - only the dot at the end has to be removed. So nothing else has to be done with that input.
It wouldn't be possible without calling multiple replace() methods. The steps in provided solution is as following:
Remove all dots in abbreviated names
Substitute lastname with firstname
Replace lastnames with their beginning letter
Remove unwanted characters
Demo:
var s = `Guilcher, G.M., Harvey, M. & Hand, J.P.
Ri Liesner, Peter Tom Collins, Michael Richards
Manco-Johnson M, Santagostino E, Ljung R.`
// Remove all dots in abbreviated names
var b = s.replace(/\b([A-Z])\./g, '$1')
// Substitute first names and lastnames
.replace(/([A-Z][\w-]+(?: +[A-Z][\w-]+)*) +([A-Z][\w-]+)\b/g, ($0, $1, $2) => {
// Replace full lastnames with their first letter
return $2 + " " + $1.replace(/\b([A-Z])\w+ */g, '$1');
})
// Remove unwanted preceding / following commas and ampersands
.replace(/(,) +([A-Z]+)\b *[,&]?/g, ' $2$1');
console.log(b);
Given your example data i would try to make guesses based on name part count = 2, since it is very hard to rely on any ,, & or \n - which means treat them all as ,.
Try this against your data and let me know of any use-cases where this fails because i am highly confident that this script will fail at some point with more data :)
let testString = "Guilcher, G.M., Harvey, M. & Hand, J.P.\nRi Liesner, Peter Tom Collins, Michael Richards\nManco-Johnson M, Santagostino E, Ljung R.";
const inputToArray = i => i
.replace(/\./g, "")
.replace(/[\n&]/g, ",")
.replace(/ ?, ?/g, ",")
.split(',');
const reducer = function(accumulator, value, index, array) {
let pos = accumulator.length - 1;
let names = value.split(' ');
if(names.length > 1) {
accumulator.push(names);
} else {
if(accumulator[pos].length > 1) accumulator[++pos] = [];
accumulator[pos].push(value);
}
return accumulator.filter(n => n.length > 0);
};
console.log(inputToArray(testString).reduce(reducer, [[]]));
Here's my approach. I tried to keep it short but complexity was surprisingly high to get the edge cases.
First I'm formatting the input, to replace & for ,, and removing ..
Then, I'm splitting the input by \n, then , and finally (spaces).
Next I'm processing the chunks. On each new segment (delimited by ,), I process the previous segment. I do this because I need to be sure that the current segment isn't an initial. If that's the case, I do my best to skip that inital-only segment and process the previous one. The previous one will have the correct initial and surname, as I have all the information I neeed.
I get the initial on the segment if there's one. This will be used on the start of the next segment to process the current one.
After finishing each line, I process again the last segment, as it wont be called otherwise.
I understand the complexity is high without using regexp, and probably would have been better to use a state machine to parse the input instead.
const isInitial = s => [...s].every(c => c === c.toUpperCase());
const generateInitial = arr => arr.reduce((a, c, i) => a + (i < arr.length - 1 ? c[0].toUpperCase() : ''), '');
const formatSegment = (words, initial) => {
if (!initial) {
initial = generateInitial(words);
}
const surname = words[words.length - 1];
return {initial, surname};
}
const doDisplay = x => x.map(x => x.surname + ' ' + x.initial).join(', ');
const doProcess = _ => {
const formatted = input.value.replace(/\./g, '').replace(/&/g, ',');
const chunks = formatted.split('\n').map(x => x.split(',').map(x => x.trim().split(' ')));
const peoples = [];
chunks.forEach(line => {
let lastSegment = null;
let lastInitial = null;
let lastInitialOnly = false;
line.forEach(segment => {
if (lastSegment) {
// if segment only contains an initial, it's the initial corresponding
// to the previous segment
const initialOnly = segment.length === 1 && isInitial(segment[0]);
if (initialOnly) {
lastInitial = segment[0];
}
// avoid processing last segments that were only initials
// this prevents adding a segment twice
if (!lastInitialOnly) {
// if segment isn't an initial, we need to generate an initial
// for the previous segment, if it doesn't already have one
const people = formatSegment(lastSegment, lastInitial);
peoples.push(people);
}
lastInitialOnly = initialOnly;
// Skip initial only segments
if (initialOnly) {
return;
}
}
lastInitial = null;
// Remove the initial from the words
// to avoid getting the initial calculated for the initial
segment = segment.filter(word => {
if (isInitial(word)) {
lastInitial = word;
return false;
}
return true;
});
lastSegment = segment;
});
// Process last segment
if (!lastInitialOnly) {
const people = formatSegment(lastSegment, lastInitial);
peoples.push(people);
}
});
return peoples;
}
process.addEventListener('click', _ => {
const peoples = doProcess();
const display = doDisplay(peoples);
output.value = display;
});
.row {
display: flex;
}
.row > * {
flex: 1 0;
}
<div class="row">
<h3>Input</h3>
<h3>Output</h3>
</div>
<div class="row">
<textarea id="input" rows="10">Guilcher, G.M., Harvey, M. & Hand, J.P.
Ri Liesner, Peter Tom Collins, Michael Richards
Manco-Johnson M, Santagostino E, Ljung R.
Jordan M, Michael Jackson & Willis B.</textarea>
<textarea id="output" rows="10"></textarea>
</div>
<button id="process" style="display: block;">Process</button>
I'm new to RegExp and to JS in general (Coming from Python), so this might be an easy question:
I'm trying to code an algebraic calculator in Javascript that receives an algebraic equation as a string, e.g.,
string = 'x^2 + 30x -12 = 4x^2 - 12x + 30';
The algorithm is already able to break the string in a single list, with all values on the right side multiplied by -1 so I can equate it all to 0, however, one of the steps to solve the equation involves creating a hashtable/dictionary, having the variable as key.
The string above results in a list eq:
eq = ['x^2', '+30x', '-12', '-4x^2', '+12x', '-30'];
I'm currently planning on iterating through this list, and using RegExp to identify both variables and the respective multiplier, so I can create a hashTable/Dictionary that will allow me to simplify the equation, such as this one:
hashTable = {
'x^2': [1, -4],
'x': [30, 12],
' ': [-12]
}
I plan on using some kind of for loop to iter through the array, and applying a match on each string to get the values I need, but I'm quite frankly, stumped.
I have already used RegExp to separate the string into the individual parts of the equation and to remove eventual spaces, but I can't imagine a way to separate -4 from x^2 in '-4x^2'.
You can try this
(-?\d+)x\^\d+.
When you execute match function :
var res = "-4x^2".match(/(-?\d+)x\^\d+/)
You will get res as an array : [ "-4x^2", "-4" ]
You have your '-4' in res[1].
By adding another group on the second \d+ (numeric char), you can retrieve the x power.
var res = "-4x^2".match(/(-?\d+)x\^(\d+)/) //res = [ "-4x^2", "-4", "2" ]
Hope it helps
If you know that the LHS of the hashtable is going to be at the end of the string. Lets say '4x', x is at the end or '-4x^2' where x^2 is at end, then we can get the number of the expression:
var exp = '-4x^2'
exp.split('x^2')[0] // will return -4
I hope this is what you were looking for.
function splitTerm(term) {
var regex = /([+-]?)([0-9]*)?([a-z](\^[0-9]+)?)?/
var match = regex.exec(term);
return {
constant: parseInt((match[1] || '') + (match[2] || 1)),
variable: match[3]
}
}
splitTerm('x^2'); // => {constant: 1, variable: "x^2"}
splitTerm('+30x'); // => {constant: 30, variable: "x"}
splitTerm('-12'); // => {constant: -12, variable: undefined}
Additionally, these tool may help you analyze and understand regular expressions:
https://regexper.com/
https://regex101.com/
http://rick.measham.id.au/paste/explain.pl
Lets say I had a variable called test and test = 123456789;. Then I have another variable called anotherTest and anotherTest = 1234;. How would I make a program that can test whether a variable has the digit 5 or not? Then, how could it sort the variables into two groups of which one group of variables has the digit "5" within it and the other without? Is there a easy way to do this?
How would I make a program that can test whether a variable has the digit 5 or not?
You can readily do that with strings and indexOf:
if (String(test).indexOf("5") !== -1) {
// It has a 5 in it
}
Then, how could it sort the variables into two groups of which one group of variables has the digit "5" within it and the other without?
You can't sort the variables into groups, but you can certainly sort values into groups. For example, this loops through an array and adds values to either the with5 or without5 array depending on whether the value contains the digit 5:
var a = [
1234,
12345,
123123,
555555
];
var with5 = [];
var without5 = [];
a.forEach(function(value) {
if (String(value).indexOf("5") === -1) {
without5.push(value);
} else {
with5.push(value);
}
});
snippet.log("with5: " + with5.join(", "));
snippet.log("without5: " + without5.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
The above assumes base 10 (decimal) strings, but you can easily do the same with hexadecimal or octal or any other base you like by using Number#toString(base). E.g.:
var s = num.toString(16);
...will assign s the value of num as a hexadecimal (base 16) string.
Loop through each character of variable test, then compare using indexOf() to see if it exists in anotherTest. If so add to one array, otherwise add to array 2.
To see if a number contains the digit "5", you can just convert the numbers to strings and then just use .indexOf("5") on each string.
var test = 123456789;
var anotherTest = 1234;
// reports whether the passed in number or string contains the
// character "5"
function containsDigit5(val) {
// convert number to string
// if already string, then it is left as is
val = "" + val;
return val.indexOf("5") >= 0;
}
containsDigit5(test); // true
containsDigit5(anotherTest); // false
The grouping part of your question is not entirely clear, but you can just call this function on each variable and add the numbers to one of two arrays.
var testNumbers = [123456789, 1234];
var has5 = [];
var doesNotHave5 = [];
// reports whether the passed in number or string contains the
// character "5"
function containsDigit5(val) {
// convert number to string
// if already string, then it is left as is
val = "" + val;
return val.indexOf("5") >= 0;
}
testNumbers.forEach(function(item) {
if (containsDigit5(item)) {
has5.push(testNumbers[i]);
} else {
doesNotHave5.push(testNumbers[i]);
}
});
You can do this with RegExp, or .indexOf. Either works:
RegEx
Everyone hates RegExp for some reason, but I like it. You can use:
var test = 123456789,
anotherTest = 1234;
/5/.test(test);
/5/.test(anotherTest);
var test = 123456789,
anotherTest = 1234;
document.write( 'test (123456789): ' + /5/.test(test) + '<br/>' );
document.write( 'anotherTest (1234): ' + /5/.test(anotherTest) );
indexOf
This can be faster in some situations, but not always, it is also a bit more "complicated", at least in my opinion:
var test = 123456789,
anotherTest = 1234;
(test+'').indexOf(5) > -1;
(anotherTest+'').indexOf(5) > -1;
var test = 123456789,
anotherTest = 1234;
document.write( 'test (123456789): ' + ((test+'').indexOf(5) > -1) + '<br/>' );
document.write( 'anotherTest (1234): ' + ((anotherTest+'').indexOf(5) > -1) + '<br/>' );