Validate if string has only numbers - java

My Java application 'A' is getting mobile number as String from another java application. So after app A gets the mobile number string, I need to validate if that mobile number String has only numbers in it. For validating that I have used a simple logic as below,
public static boolean containsOnlyDigits(String str, int n) {
for (int i = 1; i < n; i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
I am checking from i=1 as 1st character will be '+' for country code. This approach is O(n). There is another approach where we can use Double.parseDouble(str). This will throw NumberFormatException so that we can catch and consider it is an Alphanumeric String.
Which of these approaches are best based on performance?

You could try, remove the + if not useful:
/**
* Assuming that a phone number is of an international format, having `+` sign as prefix
* and with no spaces in between the numbers, validates if a string is a valid phone number.
*
* #param phone
* #return resulting boolean
*/
private boolean isValidPhoneNumber(String phone) {
if(phone == null) return false;
return Pattern.matches("\\+\\d{11,15}", phone);
}

Using regular expressions is costly. For this reason, you can easily solve this problem using the lambda notation in Java 8.
boolean numericControl = str.chars().allMatch(x -> Character.isDigit(x));

I am checking from i=1 as 1st character will be '+' for country code.
You can use the regex, \+\d{n - 1} which means the first character is + and the remaining n - 1 characters are digits. It also means that the total length of the string should be n.
public class Main {
public static void main(String[] args) {
// Tests
System.out.println(containsOnlyDigits("+123456789", 10));
System.out.println(containsOnlyDigits("+123456789", 9));
System.out.println(containsOnlyDigits("+123456789", 8));
System.out.println(containsOnlyDigits("-123456789", 9));
System.out.println(containsOnlyDigits("123456789", 9));
System.out.println(containsOnlyDigits("ABC123456", 9));
}
public static boolean containsOnlyDigits(String str, int n) {
String regex = "\\+\\d{" + (n - 1) + "}";
return str.matches(regex);
}
}
Output:
true
false
false
false
false
false

Related

Find words in String consisting of all distinct characters without using Java Collection Framework

I need your help. I am stuck on one problem, solving it for several hours.
*1. Find word containing only of various characters. Return first word if there are a few of such words.
2. #param words Input array of words
3. #return First word that containing only of various characters*
**public String findWordConsistingOfVariousCharacters(String[] words) {
throw new UnsupportedOperationException("You need to implement this method");
}**
#Test
public void testFindWordConsistingOfVariousCharacters() {
String[] input = new String[] {"aaaaaaawe", "qwer", "128883", "4321"};
String expectedResult = "qwer";
StringProcessor stringProcessor = new StringProcessor();
String result = stringProcessor.findWordConsistingOfVariousCharacters(input);
assertThat(String.format("Wrong result of method findWordConsistingOfVariousCharacters (input is %s)", Arrays.toString(input)), result, is(expectedResult));
}
Thank you in advance
Just go through the data and check whether each string is made up of only distinct characters:
public static boolean repeat(String str) {
char[] chars = str.toCharArray();
Arrays.sort(chars);//The same character will only appear in groups
for(int i = 1;i<chars.length;i++) {
if(chars[i] == chars[i - 1]) {
return false;//Same character appeared twice
}
}
return true;//There is no repeating character
}
The method above is used to check whether a string is made up of distinct characters, now loops through the data:
for(int i = 0;i<input.length;i++){
if(repeat(input[i])){
System.out.println("The answer is " + input[i] + " at index " + i);
break;//you find it! Now break the loop
}
}
Assuming the strings are all ASCII characters, use a boolean[] to mark if you have encountered that character in the word already:
boolean [] encountered = new boolean[256];
for (char c : word.toCharArray()) {
if (encountered[(int)c]) {
// not unique
} else {
encountered[(int)c] = true;
}
}

How to write a recursive method to promote a String to all possible combinations, With no loops or arrays?

public Password(int length)//a constructor that creates a random password in a given length
public boolean isPassword(String st)//retruns True if the String equals to the password.
I need to make a recursive method... to crack the password...
it contains only lower-case letters.
I can only use:
isPassword(),(charAt, equals, length, substring)
No loops, no arrays...
this is what ive done so far, i got an "a" String to the right length:
/**
* Recursive method, cracks and return
* the right string of Password p.
* #param p The Password object to crack.
* #param length The length of the password.
* #return The String combination of the password.
*/
public static String findPassword(Password p,int length)
{
String aString;//to store an "aaa.." string in the length of p
String password;//to store the password
aString = findPassword("a",length);//recursion method, gets string of a in length
password = findPassword(aString, p, 0);//recursion method, finds the password
return password;
}
public static String findPassword(String startString, int length)
{ //recursion to make "aaa..." string in the length of n.
if (startString.length() != length )//if not in the length
{
startString += "a"; //add "a" character
if(startString.length() == length)//if in the length,
{ //return String
return startString;
}
} //call the recursion if still
return findPassword(startString,length);//not in the length
}
Now I need to promote this string to all possible combinations... and I have no idea how to do so without loops or an array...
thanks!
I have an answer for you.
The idea to crack a password is to run through all possible combinations. The combinations are basically a sequence like 1,2,3,4, ... (iIrc B-adic sequences is the term in math).
For a decimal sequence, you have digits 0-9 and the rule is to overflow to the next number if you reach the end of the alphabet (9 in this case).
The decimal counting system can be applied to anything: binary numbers have an alphabet of 2 (0,1). hex numbers have an alphabet of 16 (0-9,a-f).
The passwort you are looking for has an alphabet of the allowed character set in your password. The set is represented in an array of characters. The array defines the order and the size of the set. To iterate the passwords, you apply the counting algorithm to your password-"number".
The following code does this:
public class PasswordFinder {
private static final String PASSWORD = "zxy";
private static final char[] ALPHABET = "abcdefghijklmnopqrstuvwxyz".toCharArray();
boolean isPassword(String pass) {
return (pass.equals(PASSWORD));
}
boolean findPassword(String password) {
while (!isPassword(password)) {
password = next(password);
}
return true;
}
/* recursive variant, will require up to (ALPHABET.length^(PASSWORD.length+1)) - 1 recursions */
boolean findPasswordRecursive(String password) {
if (isPassword(password)) {
return true;
}
return findPasswordRecursive(next(password));
}
private String next(String password) {
if( password.length() == 0 ) {
return "" + ALPHABET[0];
}
char nextChar = password.charAt(password.length()-1);
int idx = (nextChar - ALPHABET[0] + 1) % ALPHABET.length;
if( idx == 0 ) {
return next(password.substring(0, password.length() - 1)) + ALPHABET[0];
}
return password.substring(0, password.length() - 1) + ALPHABET[idx];
}
}
The next function does the counting:
If we receive no password (you can apply a null check here as well), we create one with the first "digit" from our alphabet:
if( password.length() == 0 ) {
return "" + ALPHABET[0];
}
We now select the char to be counted up. It is always the last digit of your sequence, the last char of the string:
char nextChar = password.charAt(password.length()-1);
To count, we calculate the index of the char in the alphabet (index magic, substract the first char from the found char), the index is increased by 1. To handle the "end of alphabet", we use the modulo operator. It will return 0 when we reached the end of the alphabet.
int idx = (nextChar - ALPHABET[0] + 1) % ALPHABET.length;
When we reach the end of the alphabet, we need to overflow to the next digit and add one to that: "9" + 1 => "10". Since overflowing is recursive, we use our counting function to add one to each digit in the password and overflow accordingly. To do this, we add 1 to the prefix of the last digit and reset the last digit to "0": "89" + 1 => next("8") + "0"
if( idx == 0 ) {
return next(password.substring(0, password.length() - 1)) + ALPHABET[0];
}
If we need not to overflow, we simply increase the last digit.
return password.substring(0, password.length() - 1) + ALPHABET[idx];
}

Check number is valid number or not [duplicate]

How would you check if a String was a number before parsing it?
This is generally done with a simple user-defined function (i.e. Roll-your-own "isNumeric" function).
Something like:
public static boolean isNumeric(String str) {
try {
Double.parseDouble(str);
return true;
} catch(NumberFormatException e){
return false;
}
}
However, if you're calling this function a lot, and you expect many of the checks to fail due to not being a number then performance of this mechanism will not be great, since you're relying upon exceptions being thrown for each failure, which is a fairly expensive operation.
An alternative approach may be to use a regular expression to check for validity of being a number:
public static boolean isNumeric(String str) {
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
Be careful with the above RegEx mechanism, though, as it will fail if you're using non-Arabic digits (i.e. numerals other than 0 through to 9). This is because the "\d" part of the RegEx will only match [0-9] and effectively isn't internationally numerically aware. (Thanks to OregonGhost for pointing this out!)
Or even another alternative is to use Java's built-in java.text.NumberFormat object to see if, after parsing the string the parser position is at the end of the string. If it is, we can assume the entire string is numeric:
public static boolean isNumeric(String str) {
ParsePosition pos = new ParsePosition(0);
NumberFormat.getInstance().parse(str, pos);
return str.length() == pos.getIndex();
}
With Apache Commons Lang 3.5 and above: NumberUtils.isCreatable or StringUtils.isNumeric.
With Apache Commons Lang 3.4 and below: NumberUtils.isNumber or StringUtils.isNumeric.
You can also use StringUtils.isNumericSpace which returns true for empty strings and ignores internal spaces in the string. Another way is to use NumberUtils.isParsable which basically checks the number is parsable according to Java. (The linked javadocs contain detailed examples for each method.)
Java 8 lambda expressions.
String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );
if you are on android, then you should use:
android.text.TextUtils.isDigitsOnly(CharSequence str)
documentation can be found here
keep it simple. mostly everybody can "re-program" (the same thing).
As #CraigTP had mentioned in his excellent answer, I also have similar performance concerns on using Exceptions to test whether the string is numerical or not. So I end up splitting the string and use java.lang.Character.isDigit().
public static boolean isNumeric(String str)
{
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;
}
According to the Javadoc, Character.isDigit(char) will correctly recognizes non-Latin digits. Performance-wise, I think a simple N number of comparisons where N is the number of characters in the string would be more computationally efficient than doing a regex matching.
UPDATE: As pointed by Jean-François Corbett in the comment, the above code would only validate positive integers, which covers the majority of my use case. Below is the updated code that correctly validates decimal numbers according to the default locale used in your system, with the assumption that decimal separator only occur once in the string.
public static boolean isStringNumeric( String str )
{
DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
char localeMinusSign = currentLocaleSymbols.getMinusSign();
if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;
boolean isDecimalSeparatorFound = false;
char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();
for ( char c : str.substring( 1 ).toCharArray() )
{
if ( !Character.isDigit( c ) )
{
if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
{
isDecimalSeparatorFound = true;
continue;
}
return false;
}
}
return true;
}
Google's Guava library provides a nice helper method to do this: Ints.tryParse. You use it like Integer.parseInt but it returns null rather than throw an Exception if the string does not parse to a valid integer. Note that it returns Integer, not int, so you have to convert/autobox it back to int.
Example:
String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);
int i1 = -1;
if (oInt1 != null) {
i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
i2 = oInt2.intValue();
}
System.out.println(i1); // prints 22
System.out.println(i2); // prints -1
However, as of the current release -- Guava r11 -- it is still marked #Beta.
I haven't benchmarked it. Looking at the source code there is some overhead from a lot of sanity checking but in the end they use Character.digit(string.charAt(idx)), similar, but slightly different from, the answer from #Ibrahim above. There is no exception handling overhead under the covers in their implementation.
Do not use Exceptions to validate your values.
Use Util libs instead like apache NumberUtils:
NumberUtils.isNumber(myStringValue);
Edit:
Please notice that, if your string starts with an 0, NumberUtils will interpret your value as hexadecimal.
NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false
Why is everyone pushing for exception/regex solutions?
While I can understand most people are fine with using try/catch, if you want to do it frequently... it can be extremely taxing.
What I did here was take the regex, the parseNumber() methods, and the array searching method to see which was the most efficient. This time, I only looked at integer numbers.
public static boolean isNumericRegex(String str) {
if (str == null)
return false;
return str.matches("-?\\d+");
}
public static boolean isNumericArray(String str) {
if (str == null)
return false;
char[] data = str.toCharArray();
if (data.length <= 0)
return false;
int index = 0;
if (data[0] == '-' && data.length > 1)
index = 1;
for (; index < data.length; index++) {
if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
return false;
}
return true;
}
public static boolean isNumericException(String str) {
if (str == null)
return false;
try {
/* int i = */ Integer.parseInt(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
The results in speed I got were:
Done with: for (int i = 0; i < 10000000; i++)...
With only valid numbers ("59815833" and "-59815833"):
Array numeric took 395.808192 ms [39.5808192 ns each]
Regex took 2609.262595 ms [260.9262595 ns each]
Exception numeric took 428.050207 ms [42.8050207 ns each]
// Negative sign
Array numeric took 355.788273 ms [35.5788273 ns each]
Regex took 2746.278466 ms [274.6278466 ns each]
Exception numeric took 518.989902 ms [51.8989902 ns each]
// Single value ("1")
Array numeric took 317.861267 ms [31.7861267 ns each]
Regex took 2505.313201 ms [250.5313201 ns each]
Exception numeric took 239.956955 ms [23.9956955 ns each]
// With Character.isDigit()
Array numeric took 400.734616 ms [40.0734616 ns each]
Regex took 2663.052417 ms [266.3052417 ns each]
Exception numeric took 401.235906 ms [40.1235906 ns each]
With invalid characters ("5981a5833" and "a"):
Array numeric took 343.205793 ms [34.3205793 ns each]
Regex took 2608.739933 ms [260.8739933 ns each]
Exception numeric took 7317.201775 ms [731.7201775 ns each]
// With a single character ("a")
Array numeric took 291.695519 ms [29.1695519 ns each]
Regex took 2287.25378 ms [228.725378 ns each]
Exception numeric took 7095.969481 ms [709.5969481 ns each]
With null:
Array numeric took 214.663834 ms [21.4663834 ns each]
Regex took 201.395992 ms [20.1395992 ns each]
Exception numeric took 233.049327 ms [23.3049327 ns each]
Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check
Disclaimer: I'm not claiming these methods are 100% optimized, they're just for demonstration of the data
Exceptions won if and only if the number is 4 characters or less, and every string is always a number... in which case, why even have a check?
In short, it is extremely painful if you run into invalid numbers frequently with the try/catch, which makes sense. An important rule I always follow is NEVER use try/catch for program flow. This is an example why.
Interestingly, the simple if char <0 || >9 was extremely simple to write, easy to remember (and should work in multiple languages) and wins almost all the test scenarios.
The only downside is that I'm guessing Integer.parseInt() might handle non ASCII numbers, whereas the array searching method does not.
For those wondering why I said it's easy to remember the character array one, if you know there's no negative signs, you can easily get away with something condensed as this:
public static boolean isNumericArray(String str) {
if (str == null)
return false;
for (char c : str.toCharArray())
if (c < '0' || c > '9')
return false;
return true;
Lastly as a final note, I was curious about the assigment operator in the accepted example with all the votes up. Adding in the assignment of
double d = Double.parseDouble(...)
is not only useless since you don't even use the value, but it wastes processing time and increased the runtime by a few nanoseconds (which led to a 100-200 ms increase in the tests). I can't see why anyone would do that since it actually is extra work to reduce performance.
You'd think that would be optimized out... though maybe I should check the bytecode and see what the compiler is doing. That doesn't explain why it always showed up as lengthier for me though if it somehow is optimized out... therefore I wonder what's going on. As a note: By lengthier, I mean running the test for 10000000 iterations, and running that program multiple times (10x+) always showed it to be slower.
EDIT: Updated a test for Character.isDigit()
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(.\\d+)?");
}
CraigTP's regular expression (shown above) produces some false positives. E.g. "23y4" will be counted as a number because '.' matches any character not the decimal point.
Also it will reject any number with a leading '+'
An alternative which avoids these two minor problems is
public static boolean isNumeric(String str)
{
return str.matches("[+-]?\\d*(\\.\\d+)?");
}
We can try replacing all the numbers from the given string with ("") ie blank space and if after that the length of the string is zero then we can say that given string contains only numbers.
Example:
boolean isNumber(String str){
if(str.length() == 0)
return false; //To check if string is empty
if(str.charAt(0) == '-')
str = str.replaceFirst("-","");// for handling -ve numbers
System.out.println(str);
str = str.replaceFirst("\\.",""); //to check if it contains more than one decimal points
if(str.length() == 0)
return false; // to check if it is empty string after removing -ve sign and decimal point
System.out.println(str);
return str.replaceAll("[0-9]","").length() == 0;
}
You can use NumberFormat#parse:
try
{
NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
// Not a number.
}
If you using java to develop Android app, you could using TextUtils.isDigitsOnly function.
Here was my answer to the problem.
A catch all convenience method which you can use to parse any String with any type of parser: isParsable(Object parser, String str). The parser can be a Class or an object. This will also allows you to use custom parsers you've written and should work for ever scenario, eg:
isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");
Here's my code complete with method descriptions.
import java.lang.reflect.*;
/**
* METHOD: isParsable<p><p>
*
* This method will look through the methods of the specified <code>from</code> parameter
* looking for a public method name starting with "parse" which has only one String
* parameter.<p>
*
* The <code>parser</code> parameter can be a class or an instantiated object, eg:
* <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
* <code>Class</code> type then only static methods are considered.<p>
*
* When looping through potential methods, it first looks at the <code>Class</code> associated
* with the <code>parser</code> parameter, then looks through the methods of the parent's class
* followed by subsequent ancestors, using the first method that matches the criteria specified
* above.<p>
*
* This method will hide any normal parse exceptions, but throws any exceptions due to
* programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
* parameter which has no matching parse methods, a NoSuchMethodException will be thrown
* embedded within a RuntimeException.<p><p>
*
* Example:<br>
* <code>isParsable(Boolean.class, "true");<br>
* isParsable(Integer.class, "11");<br>
* isParsable(Double.class, "11.11");<br>
* Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
* isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
* <p>
*
* #param parser The Class type or instantiated Object to find a parse method in.
* #param str The String you want to parse
*
* #return true if a parse method was found and completed without exception
* #throws java.lang.NoSuchMethodException If no such method is accessible
*/
public static boolean isParsable(Object parser, String str) {
Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
Method[] methods = theClass.getMethods();
// Loop over methods
for (int index = 0; index < methods.length; index++) {
Method method = methods[index];
// If method starts with parse, is public and has one String parameter.
// If the parser parameter was a Class, then also ensure the method is static.
if(method.getName().startsWith("parse") &&
(!staticOnly || Modifier.isStatic(method.getModifiers())) &&
Modifier.isPublic(method.getModifiers()) &&
method.getGenericParameterTypes().length == 1 &&
method.getGenericParameterTypes()[0] == String.class)
{
try {
foundAtLeastOne = true;
method.invoke(parser, str);
return true; // Successfully parsed without exception
} catch (Exception exception) {
// If invoke problem, try a different method
/*if(!(exception instanceof IllegalArgumentException) &&
!(exception instanceof IllegalAccessException) &&
!(exception instanceof InvocationTargetException))
continue; // Look for other parse methods*/
// Parse method refuses to parse, look for another different method
continue; // Look for other parse methods
}
}
}
// No more accessible parse method could be found.
if(foundAtLeastOne) return false;
else throw new RuntimeException(new NoSuchMethodException());
}
/**
* METHOD: willParse<p><p>
*
* A convienence method which calls the isParseable method, but does not throw any exceptions
* which could be thrown through programatic errors.<p>
*
* Use of {#link #isParseable(Object, String) isParseable} is recommended for use so programatic
* errors can be caught in development, unless the value of the <code>parser</code> parameter is
* unpredictable, or normal programtic exceptions should be ignored.<p>
*
* See {#link #isParseable(Object, String) isParseable} for full description of method
* usability.<p>
*
* #param parser The Class type or instantiated Object to find a parse method in.
* #param str The String you want to parse
*
* #return true if a parse method was found and completed without exception
* #see #isParseable(Object, String) for full description of method usability
*/
public static boolean willParse(Object parser, String str) {
try {
return isParsable(parser, str);
} catch(Throwable exception) {
return false;
}
}
To match only positive base-ten integers, that contains only ASCII digits, use:
public static boolean isNumeric(String maybeNumeric) {
return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}
A well-performing approach avoiding try-catch and handling negative numbers and scientific notation.
Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\\d*)(\\.\\d+)?(E\\d+)?$" );
public static boolean isNumeric( String value )
{
return value != null && PATTERN.matcher( value ).matches();
}
Regex Matching
Here is another example upgraded "CraigTP" regex matching with more validations.
public static boolean isNumeric(String str)
{
return str.matches("^(?:(?:\\-{1})?\\d+(?:\\.{1}\\d+)?)$");
}
Only one negative sign - allowed and must be in beginning.
After negative sign there must be digit.
Only one decimal sign . allowed.
After decimal sign there must be digit.
Regex Test
1 -- **VALID**
1. -- INVALID
1.. -- INVALID
1.1 -- **VALID**
1.1.1 -- INVALID
-1 -- **VALID**
--1 -- INVALID
-1. -- INVALID
-1.1 -- **VALID**
-1.1.1 -- INVALID
Here is my class for checking if a string is numeric. It also fixes numerical strings:
Features:
Removes unnecessary zeros ["12.0000000" -> "12"]
Removes unnecessary zeros ["12.0580000" -> "12.058"]
Removes non numerical characters ["12.00sdfsdf00" -> "12"]
Handles negative string values ["-12,020000" -> "-12.02"]
Removes multiple dots ["-12.0.20.000" -> "-12.02"]
No extra libraries, just standard Java
Here you go...
public class NumUtils {
/**
* Transforms a string to an integer. If no numerical chars returns a String "0".
*
* #param str
* #return retStr
*/
static String makeToInteger(String str) {
String s = str;
double d;
d = Double.parseDouble(makeToDouble(s));
int i = (int) (d + 0.5D);
String retStr = String.valueOf(i);
System.out.printf(retStr + " ");
return retStr;
}
/**
* Transforms a string to an double. If no numerical chars returns a String "0".
*
* #param str
* #return retStr
*/
static String makeToDouble(String str) {
Boolean dotWasFound = false;
String orgStr = str;
String retStr;
int firstDotPos = 0;
Boolean negative = false;
//check if str is null
if(str.length()==0){
str="0";
}
//check if first sign is "-"
if (str.charAt(0) == '-') {
negative = true;
}
//check if str containg any number or else set the string to '0'
if (!str.matches(".*\\d+.*")) {
str = "0";
}
//Replace ',' with '.' (for some european users who use the ',' as decimal separator)
str = str.replaceAll(",", ".");
str = str.replaceAll("[^\\d.]", "");
//Removes the any second dots
for (int i_char = 0; i_char < str.length(); i_char++) {
if (str.charAt(i_char) == '.') {
dotWasFound = true;
firstDotPos = i_char;
break;
}
}
if (dotWasFound) {
String befDot = str.substring(0, firstDotPos + 1);
String aftDot = str.substring(firstDotPos + 1, str.length());
aftDot = aftDot.replaceAll("\\.", "");
str = befDot + aftDot;
}
//Removes zeros from the begining
double uglyMethod = Double.parseDouble(str);
str = String.valueOf(uglyMethod);
//Removes the .0
str = str.replaceAll("([0-9])\\.0+([^0-9]|$)", "$1$2");
retStr = str;
if (negative) {
retStr = "-"+retStr;
}
return retStr;
}
static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
}
Exceptions are expensive, but in this case the RegEx takes much longer. The code below shows a simple test of two functions -- one using exceptions and one using regex. On my machine the RegEx version is 10 times slower than the exception.
import java.util.Date;
public class IsNumeric {
public static boolean isNumericOne(String s) {
return s.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
public static boolean isNumericTwo(String s) {
try {
Double.parseDouble(s);
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String [] args) {
String test = "12345.F";
long before = new Date().getTime();
for(int x=0;x<1000000;++x) {
//isNumericTwo(test);
isNumericOne(test);
}
long after = new Date().getTime();
System.out.println(after-before);
}
}
// please check below code
public static boolean isDigitsOnly(CharSequence str) {
final int len = str.length();
for (int i = 0; i < len; i++) {
if (!Character.isDigit(str.charAt(i))) {
return false;
}
}
return true;
}
You can use the java.util.Scanner object.
public static boolean isNumeric(String inputData) {
Scanner sc = new Scanner(inputData);
return sc.hasNextInt();
}
// only int
public static boolean isNumber(int num)
{
return (num >= 48 && c <= 57); // 0 - 9
}
// is type of number including . - e E
public static boolean isNumber(String s)
{
boolean isNumber = true;
for(int i = 0; i < s.length() && isNumber; i++)
{
char c = s.charAt(i);
isNumber = isNumber & (
(c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
);
}
return isInteger;
}
// is type of number
public static boolean isInteger(String s)
{
boolean isInteger = true;
for(int i = 0; i < s.length() && isInteger; i++)
{
char c = s.charAt(i);
isInteger = isInteger & ((c >= '0' && c <= '9'));
}
return isInteger;
}
public static boolean isNumeric(String s)
{
try
{
Double.parseDouble(s);
return true;
}
catch (Exception e)
{
return false;
}
}
This a simple example for this check:
public static boolean isNumericString(String input) {
boolean result = false;
if(input != null && input.length() > 0) {
char[] charArray = input.toCharArray();
for(char c : charArray) {
if(c >= '0' && c <= '9') {
// it is a digit
result = true;
} else {
result = false;
break;
}
}
}
return result;
}
I have illustrated some conditions to check numbers and decimals without using any API,
Check Fix Length 1 digit number
Character.isDigit(char)
Check Fix Length number (Assume length is 6)
String number = "132452";
if(number.matches("([0-9]{6})"))
System.out.println("6 digits number identified");
Check Varying Length number between (Assume 4 to 6 length)
// {n,m} n <= length <= m
String number = "132452";
if(number.matches("([0-9]{4,6})"))
System.out.println("Number Identified between 4 to 6 length");
String number = "132";
if(!number.matches("([0-9]{4,6})"))
System.out.println("Number not in length range or different format");
Check Varying Length decimal number between (Assume 4 to 7 length)
// It will not count the '.' (Period) in length
String decimal = "132.45";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1.12";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "1234";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "-10.123";
if(decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Numbers Identified between 4 to 7");
String decimal = "123..4";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "132";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
String decimal = "1.1";
if(!decimal.matches("(-?[0-9]+(\.)?[0-9]*){4,6}"))
System.out.println("Decimal not in range or different format");
Hope it will help manyone.
Based off of other answers I wrote my own and it doesn't use patterns or parsing with exception checking.
It checks for a maximum of one minus sign and checks for a maximum of one decimal point.
Here are some examples and their results:
"1", "-1", "-1.5" and "-1.556" return true
"1..5", "1A.5", "1.5D", "-" and "--1" return false
Note: If needed you can modify this to accept a Locale parameter and pass that into the DecimalFormatSymbols.getInstance() calls to use a specific Locale instead of the current one.
public static boolean isNumeric(final String input) {
//Check for null or blank string
if(input == null || input.isBlank()) return false;
//Retrieve the minus sign and decimal separator characters from the current Locale
final var localeMinusSign = DecimalFormatSymbols.getInstance().getMinusSign();
final var localeDecimalSeparator = DecimalFormatSymbols.getInstance().getDecimalSeparator();
//Check if first character is a minus sign
final var isNegative = input.charAt(0) == localeMinusSign;
//Check if string is not just a minus sign
if (isNegative && input.length() == 1) return false;
var isDecimalSeparatorFound = false;
//If the string has a minus sign ignore the first character
final var startCharIndex = isNegative ? 1 : 0;
//Check if each character is a number or a decimal separator
//and make sure string only has a maximum of one decimal separator
for (var i = startCharIndex; i < input.length(); i++) {
if(!Character.isDigit(input.charAt(i))) {
if(input.charAt(i) == localeDecimalSeparator && !isDecimalSeparatorFound) {
isDecimalSeparatorFound = true;
} else return false;
}
}
return true;
}
For non-negative number use this
public boolean isNonNegativeNumber(String str) {
return str.matches("\\d+");
}
For any number use this
public boolean isNumber(String str) {
return str.matches("-?\\d+");
}
I modified CraigTP's solution to accept scientific notation and both dot and comma as decimal separators as well
^-?\d+([,\.]\d+)?([eE]-?\d+)?$
example
var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false
That's why I like the Try* approach in .NET. In addition to the traditional Parse method that's like the Java one, you also have a TryParse method. I'm not good in Java syntax (out parameters?), so please treat the following as some kind of pseudo-code. It should make the concept clear though.
boolean parseInteger(String s, out int number)
{
try {
number = Integer.parseInt(myString);
return true;
} catch(NumberFormatException e) {
return false;
}
}
Usage:
int num;
if (parseInteger("23", out num)) {
// Do something with num.
}
Parse it (i.e. with Integer#parseInt ) and simply catch the exception. =)
To clarify: The parseInt function checks if it can parse the number in any case (obviously) and if you want to parse it anyway, you are not going to take any performance hit by actually doing the parsing.
If you would not want to parse it (or parse it very, very rarely) you might wish to do it differently of course.
You can use NumberUtils.isCreatable() from Apache Commons Lang.
Since NumberUtils.isNumber will be deprecated in 4.0, so use NumberUtils.isCreatable() instead.
Java 8 Stream, lambda expression, functional interface
All cases handled (string null, string empty etc)
String someString = null; // something="", something="123abc", something="123123"
boolean isNumeric = Stream.of(someString)
.filter(s -> s != null && !s.isEmpty())
.filter(Pattern.compile("\\D").asPredicate().negate())
.mapToLong(Long::valueOf)
.boxed()
.findAny()
.isPresent();

Recursive half equal string

I'm having trouble building a recursive function in java which returns true if more than half of the characters are equal and false otherwise.
The equal characters must be in the same index.
for example:
Imhereman Imhereasd
are ok since there are 6 equal characters at 0,1,2,3,4,5 indexes and 6 is bigger than half of the string length.
on the other hand:
Imhereman Imhxxisuw
Is not ok since there are 3 equal characters at 0,1,2 and 3 is smaller than the half of the string length.
the prototype is :
public static Boolean diffp(String s1, String s2);
any suggestions?
I only know that I should compare s1[0] and s2[0] and each time "cut" the string with substr().
But how do I count the number of equalities so I know if I should return true or false?
thanks in advance
You need to give the recursive function a "goal" - return true when something happens. The goal is "we need this many characters to match". Every time we find a match we call the function again, but with the parameter reduced by one (one less match needed to be found).
You call it initially with n = s1.length() / 2, obviously.
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
System.out.println(checkVal("Imhereman", "Imaereads", 5));
// your code goes here
}
public static Boolean checkVal(String s1, String s2, int n)
{
System.out.println("comparing '" + s1 + "' and '" + s2 + "' with n = " + n + " matches to go");
if(n == 0) return true;
if(s1.length() == 0 || s2.length() == 0) return false;
if(s1.charAt(0) == s2.charAt(0)) n--;
return checkVal(s1.substring(1), s2.substring(1), n);
}
}
Output (including the intermediate print which you obviously will want to remove in the final code - it's there to show what is going on):
comparing 'Imhereman' and 'Imaereads' with n = 5 matches to go
comparing 'mhereman' and 'maereads' with n = 4 matches to go
comparing 'hereman' and 'aereads' with n = 3 matches to go
comparing 'ereman' and 'ereads' with n = 3 matches to go
comparing 'reman' and 'reads' with n = 2 matches to go
comparing 'eman' and 'eads' with n = 1 matches to go
comparing 'man' and 'ads' with n = 0 matches to go
true
public class TestClass {
public static int count = 0;
public static void main(String[] args) {
String s1 = "abdefgh";
String s2 = "abcdepqrs";
checkVal(s1, s2, 0);
System.out.println(count);
if(count>=(s1.length()/2))
{
System.out.println("accept");
}
else{
System.out.println("Dont Accept");
}
}
public static void checkVal(String s1, String s2, int pos) {
if (pos == s1.length()) {
return;
}
if (s1.charAt(pos) == s2.charAt(pos)) {
count++;
}
checkVal(s1, s2, pos + 1);
}
}
O/P :
s1="abcdefgh" s2="abcdepqrs"
op: 5
accept
s1="abcdefgh" s2="abdepqrs"
op: 2
Dont Accept
PS: Please let me know if I have misunderstood the question...

Matching the occurrence and pattern of characters of String2 in String1

I was asked this question in a phone interview for summer internship, and tried to come up with a n*m complexity solution (although it wasn't accurate too) in Java.
I have a function that takes 2 strings, suppose "common" and "cmn". It should return True based on the fact that 'c', 'm', 'n' are occurring in the same order in "common". But if the arguments were "common" and "omn", it would return False because even though they are occurring in the same order, but 'm' is also appearing after 'o' (which fails the pattern match condition)
I have worked over it using Hashmaps, and Ascii arrays, but didn't get a convincing solution yet! From what I have read till now, can it be related to Boyer-Moore, or Levenshtein Distance algorithms?
Hoping for respite at stackoverflow! :)
Edit: Some of the answers talk about reducing the word length, or creating a hashset. But per my understanding, this question cannot be done with hashsets because occurrence/repetition of each character in first string has its own significance. PASS conditions- "con", "cmn", "cm", "cn", "mn", "on", "co". FAIL conditions that may seem otherwise- "com", "omn", "mon", "om". These are FALSE/FAIL because "o" is occurring before as well as after "m". Another example- "google", "ole" would PASS, but "google", "gol" would fail because "o" is also appearing before "g"!
I think it's quite simple. Run through the pattern and fore every character get the index of it's last occurence in the string. The index must always increase, otherwise return false.
So in pseudocode:
index = -1
foreach c in pattern
checkindex = string.lastIndexOf(c)
if checkindex == -1 //not found
return false
if checkindex < index
return false
if string.firstIndexOf(c) < index //characters in the wrong order
return false
index = checkindex
return true
Edit: you could further improve the code by passing index as the starting index to the lastIndexOf method. Then you would't have to compare checkindex with index and the algorithm would be faster.
Updated: Fixed a bug in the algorithm. Additional condition added to consider the order of the letters in the pattern.
An excellent question and couple of hours of research and I think I have found the solution. First of all let me try explaining the question in a different approach.
Requirement:
Lets consider the same example 'common' (mainString) and 'cmn'(subString). First we need to be clear that any characters can repeat within the mainString and also the subString and since its pattern that we are concentrating on, the index of the character play a great role to. So we need to know:
Index of the character (least and highest)
Lets keep this on hold and go ahead and check the patterns a bit more. For the word common, we need to find whether the particular pattern cmn is present or not. The different patters possible with common are :- (Precedence apply )
c -> o
c -> m
c -> n
o -> m
o -> o
o -> n
m -> m
m -> o
m -> n
o -> n
At any moment of time this precedence and comparison must be valid. Since the precedence plays a huge role, we need to have the index of each unique character Instead of storing the different patterns.
Solution
First part of the solution is to create a Hash Table with the following criteria :-
Create a Hash Table with the key as each character of the mainString
Each entry for a unique key in the Hash Table will store two indices i.e lowerIndex and higherIndex
Loop through the mainString and for every new character, update a new entry of lowerIndex into the Hash with the current index of the character in mainString.
If Collision occurs, update the current index with higherIndex entry, do this until the end of String
Second and main part of pattern matching :-
Set Flag as False
Loop through the subString and for
every character as the key, retreive
the details from the Hash.
Do the same for the very next character.
Just before loop increment, verify two conditions
If highestIndex(current character) > highestIndex(next character) Then
Pattern Fails, Flag <- False, Terminate Loop
// This condition is applicable for almost all the cases for pattern matching
Else If lowestIndex(current character) > lowestIndex(next character) Then
Pattern Fails, Flag <- False, Terminate Loop
// This case is explicitly for cases in which patterns like 'mon' appear
Display the Flag
N.B : Since I am not so versatile in Java, I did not submit the code. But some one can try implementing my idea
I had myself done this question in an inefficient manner, but it does give accurate result! I would appreciate if anyone can make out an an efficient code/algorithm from this!
Create a function "Check" which takes 2 strings as arguments. Check each character of string 2 in string 1. The order of appearance of each character of s2 should be verified as true in S1.
Take character 0 from string p and traverse through the string s to find its index of first occurrence.
Traverse through the filled ascii array to find any value more than the index of first occurrence.
Traverse further to find the last occurrence, and update the ascii array
Take character 1 from string p and traverse through the string s to find the index of first occurence in string s
Traverse through the filled ascii array to find any value more than the index of first occurrence. if found, return False.
Traverse further to find the last occurrence, and update the ascii array
As can be observed, this is a bruteforce method...I guess O(N^3)
public class Interview
{
public static void main(String[] args)
{
if (check("google", "oge"))
System.out.println("yes");
else System.out.println("sorry!");
}
public static boolean check (String s, String p)
{
int[] asciiArr = new int[256];
for(int pIndex=0; pIndex<p.length(); pIndex++) //Loop1 inside p
{
for(int sIndex=0; sIndex<s.length(); sIndex++) //Loop2 inside s
{
if(p.charAt(pIndex) == s.charAt(sIndex))
{
asciiArr[s.charAt(sIndex)] = sIndex; //adding char from s to its Ascii value
for(int ascIndex=0; ascIndex<256; ) //Loop 3 for Ascii Array
{
if(asciiArr[ascIndex]>sIndex) //condition to check repetition
return false;
else ascIndex++;
}
}
}
}
return true;
}
}
Isn't it doable in O(n log n)?
Step 1, reduce the string by eliminating all characters that appear to the right. Strictly speaking you only need to eliminate characters if they appear in the string you're checking.
/** Reduces the maximal subsequence of characters in container that contains no
* character from container that appears to the left of the same character in
* container. E.g. "common" -> "cmon", and "whirlygig" -> "whrlyig".
*/
static String reduceContainer(String container) {
SparseVector charsToRight = new SparseVector(); // Like a Bitfield but sparse.
StringBuilder reduced = new StringBuilder();
for (int i = container.length(); --i >= 0;) {
char ch = container.charAt(i);
if (charsToRight.add(ch)) {
reduced.append(ch);
}
}
return reduced.reverse().toString();
}
Step 2, check containment.
static boolean containsInOrder(String container, String containee) {
int containerIdx = 0, containeeIdx = 0;
int containerLen = container.length(), containeeLen == containee.length();
while (containerIdx < containerLen && containeeIdx < containeeLen) {
// Could loop over codepoints instead of code-units, but you get the point...
if (container.charAt(containerIdx) == containee.charAt(containeeIdx)) {
++containeeIdx;
}
++containerIdx;
}
return containeeIdx == containeeLen;
}
And to answer your second question, no, Levenshtein distance won't help you since it has the property that if you swap the arguments the output is the same, but the algo you want does not.
public class StringPattern {
public static void main(String[] args) {
String inputContainer = "common";
String inputContainees[] = { "cmn", "omn" };
for (String containee : inputContainees)
System.out.println(inputContainer + " " + containee + " "
+ containsCommonCharsInOrder(inputContainer, containee));
}
static boolean containsCommonCharsInOrder(String container, String containee) {
Set<Character> containerSet = new LinkedHashSet<Character>() {
// To rearrange the order
#Override
public boolean add(Character arg0) {
if (this.contains(arg0))
this.remove(arg0);
return super.add(arg0);
}
};
addAllPrimitiveCharsToSet(containerSet, container.toCharArray());
Set<Character> containeeSet = new LinkedHashSet<Character>();
addAllPrimitiveCharsToSet(containeeSet, containee.toCharArray());
// retains the common chars in order
containerSet.retainAll(containeeSet);
return containerSet.toString().equals(containeeSet.toString());
}
static void addAllPrimitiveCharsToSet(Set<Character> set, char[] arr) {
for (char ch : arr)
set.add(ch);
}
}
Output:
common cmn true
common omn false
I would consider this as one of the worst pieces of code I have ever written or one of the worst code examples in stackoverflow...but guess what...all your conditions are met!
No algorithm could really fit the need, so I just used bruteforce...test it out...
And I could just care less for space and time complexity...my aim was first to try and solve it...and maybe improve it later!
public class SubString {
public static void main(String[] args) {
SubString ss = new SubString();
String[] trueconditions = {"con", "cmn", "cm", "cn", "mn", "on", "co" };
String[] falseconditions = {"com", "omn", "mon", "om"};
System.out.println("True Conditions : ");
for (String str : trueconditions) {
System.out.println("SubString? : " + str + " : " + ss.test("common", str));
}
System.out.println("False Conditions : ");
for (String str : falseconditions) {
System.out.println("SubString? : " + str + " : " + ss.test("common", str));
}
System.out.println("SubString? : ole : " + ss.test("google", "ole"));
System.out.println("SubString? : gol : " + ss.test("google", "gol"));
}
public boolean test(String original, String match) {
char[] original_array = original.toCharArray();
char[] match_array = match.toCharArray();
int[] value = new int[match_array.length];
int index = 0;
for (int i = 0; i < match_array.length; i++) {
for (int j = index; j < original_array.length; j++) {
if (original_array[j] != original_array[j == 0 ? j : j-1] && contains(match.substring(0, i), original_array[j])) {
value[i] = 2;
} else {
if (match_array[i] == original_array[j]) {
if (value[i] == 0) {
if (contains(original.substring(0, j == 0 ? j : j-1), match_array[i])) {
value[i] = 2;
} else {
value[i] = 1;
}
}
index = j + 1;
}
}
}
}
for (int b : value) {
if (b != 1) {
return false;
}
}
return true;
}
public boolean contains(String subStr, char ch) {
for (char c : subStr.toCharArray()) {
if (ch == c) {
return true;
}
}
return false;
}
}
-IvarD
I think this one is not a test of your computer science fundamentals, more what you would practically do within the Java programming environment.
You could construct a regular expression out of the second argument, i.e ...
omn -> o.*m[^o]*n
... and then test candidate string against this by either using String.matches(...) or using the Pattern class.
In generic form, the construction of the RegExp should be along the following lines.
exp -> in[0].* + for each x : 2 -> in.lenght { (in[x-1] +
[^in[x-2]]* + in[x]) }
for example:
demmn -> d.*e[^d]*m[^e]*m[^m]*n
I tried it myself in a different way. Just sharing my solution.
public class PatternMatch {
public static boolean matchPattern(String str, String pat) {
int slen = str.length();
int plen = pat.length();
int prevInd = -1, curInd;
int count = 0;
for (int i = 0; i < slen; i++) {
curInd = pat.indexOf(str.charAt(i));
if (curInd != -1) {
if(prevInd == curInd)
continue;
else if(curInd == (prevInd+1))
count++;
else if(curInd == 0)
count = 1;
else count = 0;
prevInd = curInd;
}
if(count == plen)
return true;
}
return false;
}
public static void main(String[] args) {
boolean r = matchPattern("common", "on");
System.out.println(r);
}
}

Categories