How to make substring() read a string until a certain character? - java

I want to create a substring say:
String s1 = "derp123";
s2 = s1.substring(0, *index where there's a number*);
Is there any way I can achieve this other than by using the replaceAll method?
I don't want to replace all the numbers in the String, I want to stop reading the string once the method detects a number 0-9.

For this, regular expression is your friend.
I'll just show you the code for your example, but you should learn more about the power (and limitations) of regular expressions. See javadoc of Pattern.
String s1 = "derp123";
Matcher m = Pattern.compile("^\\D*").matcher(s1);
if (m.find())
System.out.println(m.group()); // prints: derp
Note that the replaceAll() method shown in comments is also using a regular expression.

Here is what you want.
String s1 = "derp123";
String patternStr = "[0-9]";
Matcher matcher = Pattern.compile(patternStr).matcher(s1);
if (matcher.find()) {
System.out.println(s1.substring(0, matcher.start()));
}
And this will give you the string part without numbers

Since OP said that he did not want to use replace and therefore regex this is my suggestion. Note, the REGEX version already given is much more elegant in my opinion I'm only providing this to show that are others ways to do so.
String s1 = "blahblah1234";
String s2 = s1.substring(0, firstNumberPos(s1));
System.out.println(s2);
And the firstNumberPos definition
public static int firstNumberPos(String str){
for ( int i=0; i<str.length(); i++ ){
if ( str.charAt(i) >= '0' && str.charAt(i) <= '9'){
return i;
}
}
return str.length();
}
Note that I didn't care about the null points, you still have to check it.

Related

how to check string contain any character other than number in java?

I want to check String contain any character or special character other than number.I wrote following code for this
String expression = "[^a-zA-z]";
Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(jTextFieldPurchaseOrder.getText().toString().trim());
It is working fine when i am taking value from jTextField and checking my condition. But giving error when checking String from DTO as below
list.get(0).getChalan_trans_id().toString().trim().matches("[^a-zA-z]");
Where list is arraylist of DTO.
I am not getting where am I going wrong?
Thanks
If you want to check if there is a non-digit character, you can use .*\\D.*:
if (list.get(0).getChalan_trans_id().toString().trim().matches(".*\\D.*")) {
//non-digit found, handle it
}
or, maybe easier, do it the other way around:
if (list.get(0).getChalan_trans_id().toString().trim().matches("\\d*")) {
//only digits found
}
There's probably a more efficient way than regular expressions. Regular expressions are powerful, but can be overkill for a simple task like this.
Something like this ought to work, and I would expect it to be quicker.
static boolean hasNonNumber(String s) {
for (int i = 0; i < s.length(); ++i) {
char c = s.charAt(i);
if (!Character.isDigit(c)) {
return true;
}
}
return false;
}

How to find the text between ( and )

I have a few strings which are like this:
text (255)
varchar (64)
...
I want to find out the number between ( and ) and store that in a string. That is, obviously, store these lengths in strings.
I have the rest of it figured out except for the regex parsing part.
I'm having trouble figuring out the regex pattern.
How do I do this?
The sample code is going to look like this:
Matcher m = Pattern.compile("<I CANT FIGURE OUT WHAT COMES HERE>").matcher("text (255)");
Also, I'd like to know if there's a cheat sheet for regex parsing, from where one can directly pick up the regex patterns
I would use a plain string match
String s = "text (255)";
int start = s.indexOf('(')+1;
int end = s.indexOf(')', start);
if (end < 0) {
// not found
} else {
int num = Integer.parseInt(s.substring(start, end));
}
You can use regex as sometimes this makes your code simpler, but that doesn't mean you should in all cases. I suspect this is one where a simple string indexOf and substring will not only be faster, and shorter but more importantly, easier to understand.
You can use this pattern to match any text between parentheses:
\(([^)]*)\)
Or this to match just numbers (with possible whitespace padding):
\(\s*(\d+)\s*\)
Of course, to use this in a string literal, you have to escape the \ characters:
Matcher m = Pattern.compile("\\(\\s*(\\d+)\\s*\\)")...
Here is some example code:
import java.util.regex.*;
class Main
{
public static void main(String[] args)
{
String txt="varchar (64)";
String re1=".*?"; // Non-greedy match on filler
String re2="\\((\\d+)\\)"; // Round Braces 1
Pattern p = Pattern.compile(re1+re2,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
Matcher m = p.matcher(txt);
if (m.find())
{
String rbraces1=m.group(1);
System.out.print("("+rbraces1.toString()+")"+"\n");
}
}
}
This will print out any (int) it finds in the input string, txt.
The regex is \((\d+)\) to match any numbers between ()
int index1 = string.indexOf("(")
int index2 = string.indexOf(")")
String intValue = string.substring(index1+1, index2-1);
Matcher m = Pattern.compile("\\((\\d+)\\)").matcher("text (255)");
if (m.find()) {
int len = Integer.parseInt (m.group(1));
System.out.println (len);
}

replaceAll boundaries and exceptions

I'm trying to use replaceAll to eliminate all of the whitespace in a string with the exception of two areas.
If my string is
AB CD #E F# #GH I# JK L M
then I want it to output as
ABCD#E F##GH I#IJKLM
Currently, it is outputting ABCD#EF##GH#IJKLM without discriminating the # characters. Is there a way to do that with regular expressions on replaceAll?
String s1 = "AB CD #E F# #GH I# JK L M";
s1 = s1.replaceAll("\\s+", "");
System.out.println(s1);
I'm not good at regular expressions. I will use a loop for this.
String s1 = "AB CD #E F# #GH I# JK L M";
StringBuilder sb = new StringBuilder();
boolean keepSpace = false;
for(int i = 0; i < s1.length; i++){
char c = s1.charAt(i);
if(keepSpace || c != ' ')
sb.append(c);
if(c == '#')
keepSpace = !keepSpace;
}
s1 = sb.toString();
System.out.println(s1);
You're looking for this positive lookahead based regex in replaceAll:
String repl = str.replaceAll("\\s+(?=(?:(?:[^#]*#){2})*[^#]*$)", "");
Live Demo: http://ideone.com/nFQhVt
Explanation: This regex is using a positive lookahead that basically is matching 0 or more occurrences of a pair of some text until a hash (#) is found i.e. ([^#]*"){2} on the right hand side (RHS) of every match of a space.
Which in simple term means replace a space only if it is outside pair of hash signs, since all the matches inside hash will have odd number of [^#]*# matches on RHS.
Try
s1 = s1.replaceAll("\\s+(?=(?:[^#]*#[^#]*#)*[^#]*$)", "");
It will only replace spaces when there are an even number of # ahead in the string.
And it is therefore far from foolproof, but it may be good enough.
You could always test the string first to make sure it contains an even number of #.

How to extract specific substring from a bigger string java

I have the following string:
String n = "(.........)(......)(.......)(......) etc"
I want to write a method which will fill a List<String> with every substring of n which is between ( and ) . Thank you in advance!
It can be done in one line:
String[] parts = input.replaceAll("(^.*\\()|(\\).*$)", "").split("\\)\\(");
The call to replaceAll() strips off the leasing and trailing brackets (plus any other junk characters before/after those first/last brackets), then you just split() on bracket pairs.
I'm not very familiar with the String methods, so I'm sure there's a way that it could be done without having to code it yourself, and just using some fancy method, but here you go:
Tested, works 100% perfect :)
String string = "(stack)(over)(flow)";
ArrayList<String> subStrings = new ArrayList<String>();
for(int c = 0; c < string.length(); c++) {
if(string.charAt(c) == '(') {
c++;
String newString = "";
for(;c < string.length() && string.charAt(c) != ')'; c++) {
newString += string.charAt(c);
}
subStrings.add(newString);
}
}
If the (...) pairs aren't nested, you can use a regular expression in Java. Take a look at the java.util.regex.Pattern class.
I made this regex version, but it's kind of lengthy. I'm sure it could be improved upon. (note: "n" is your input string)
Pattern p = Pattern.compile("\\((.*?)\\)");
Matcher matcher = p.matcher(n);
List<String> list = new ArrayList<String>();
while (matcher.find())
{
list.add(matcher.group(1)); // 1 == stuff between the ()'s
}
This should work:
String in = "(bla)(die)(foo)";
in = in .substring(1,in.length()-1);
String[] out = in .split(Pattern.quote(")("));

Use regex to replace sequences in a string with modified characters

I am trying to solve a codingbat problem using regular expressions whether it works on the website or not.
So far, I have the following code which does not add a * between the two consecutive equal characters. Instead, it just bulldozes over them and replaces them with a set string.
public String pairStar(String str) {
Pattern pattern = Pattern.compile("([a-z])\\1", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
if(matcher.find())
matcher.replaceAll(str);//this is where I don't know what to do
return str;
}
I want to know how I could keep using regex and replace the whole string. If needed, I think a recursive system could help.
This works:
while(str.matches(".*(.)\\1.*")) {
str = str.replaceAll("(.)\\1", "$1*$1");
}
return str;
Explanation of the regex:
The search regex (.)\\1:
(.) means "any character" (the .) and the brackets create a group - group 1 (the first left bracket)
\\1, which in regex is \1 (a java literal String must escape a backslash with another backslash) means "the first group" - this kind of term is called a "back reference"
So together (.)\1 means "any repeated character"
The replacement regex $1*$1:
The $1 term means "the content captured as group 1"
Recursive solution:
Technically, the solution called for on that site is a recursive solution, so here is recursive implementation:
public String pairStar(String str) {
if (!str.matches(".*(.)\\1.*")) return str;
return pairStar(str.replaceAll("(.)\\1", "$1*$1"));
}
FWIW, here's a non-recursive solution:
public String pairStar(String str) {
int len = str.length();
StringBuilder sb = new StringBuilder(len*2);
char last = '\0';
for (int i=0; i < len; ++i) {
char c = str.charAt(i);
if (c == last) sb.append('*');
sb.append(c);
last = c;
}
return sb.toString();
}
I dont know java, but I believe there is replace function for string in java or with regular expression. Your match string would be
([a-z])\\1
And the replace string would be
$1*$1
After some searching I think you are looking for this,
str.replaceAll("([a-z])\\1", "$1*$1").replaceAll("([a-z])\\1", "$1*$1");
This is my own solutions.
Recursive solution (which is probably more or less the solution that the problem is designed for)
public String pairStar(String str) {
if (str.length() <= 1) return str;
else return str.charAt(0) +
(str.charAt(0) == str.charAt(1) ? "*" : "") +
pairStar(str.substring(1));
}
If you want to complain about substring, then you can write a helper function pairStar(String str, int index) which does the actual recursion work.
Regex one-liner one-function-call solution
public String pairStar(String str) {
return str.replaceAll("(.)(?=\\1)", "$1*");
}
Both solution has the same spirit. They both check whether the current character is the same as the next character or not. If they are the same then insert a * between the 2 identical characters. Then we move on to check the next character. This is to produce the expected output a*a*a*a from input aaaa.
The normal regex solution of "(.)\\1" has a problem: it consumes 2 characters per match. As a result, we failed to compare whether the character after the 2nd character is the same character. The look-ahead is used to resolve this problem - it will do comparison with the next character without consuming it.
This is similar to the recursive solution, where we compare the next character str.charAt(0) == str.charAt(1), while calling the function recursively on the substring with only the current character removed pairStar(str.substring(1).

Categories

Resources