I need to get a substring from a java string Tokenizer - java

I need to get a substring from a java string tokenizer.
My inpunt string is = Pizza-1*Nutella-20*Chicken-65*
StringTokenizer productsTokenizer = new StringTokenizer("Pizza-1*Nutella-20*Chicken-65*", "*");
do
{
try
{
int pos = productsTokenizer .nextToken().indexOf("-");
String product = productsTokenizer .nextToken().substring(0, pos+1);
String count= productsTokenizer .nextToken().substring(pos, pos+1);
System.out.println(product + " " + count);
}
catch(Exception e)
{
}
}
while(productsTokenizer .hasMoreTokens());
My output must be:
Pizza 1
Nutella 20
Chicken 65
I need the product value and the count value in separate variables to insert that values in the Data Base.
I hope you can help me.

You could use String.split() as
String[] products = "Pizza-1*Nutella-20*Chicken-65*".split("\\*");
for (String product : products) {
String[] prodNameCount = product.split("\\-");
System.out.println(prodNameCount[0] + " " + prodNameCount[1]);
}
Output
Pizza 1
Nutella 20
Chicken 65

You invoke the nextToken() method 3 times. That will get you 3 different tokens
int pos = productsTokenizer .nextToken().indexOf("-");
String product = productsTokenizer .nextToken().substring(0, pos+1);
String count= productsTokenizer .nextToken().substring(pos, pos+1);
Instead you should do something like:
String token = productsTokenizer .nextToken();
int pos = token.indexOf("-");
String product = token.substring(...);
String count= token.substring(...);
I'll let you figure out the proper indexes for the substring() method.
Also instead of using a do/while structure it is better to just use a while loop:
while(productsTokenizer .hasMoreTokens())
{
// add your code here
}
That is don't assume there is a token.

An alternative answer you may want to use if your input grows:
// find all strings that match START or '*' followed by the name (matched),
// a hyphen and then a positive number (not starting with 0)
Pattern p = Pattern.compile("(?:^|[*])(\\w+)-([1-9]\\d*)");
Matcher finder = p.matcher(products);
while (finder.find()) {
// possibly check if the new match directly follows the previous one
String product = finder.group(1);
int count = Integer.valueOf(finder.group(2));
System.out.printf("Product: %s , count %d%n", product, count);
}

Some people dislike regex, but this is a good application for them. All you need to use is "(\\w+)-(\\d{1,})\\*" as your pattern. Here's a toy example:
String template = "Pizza-1*Nutella-20*Chicken-65*";
String pattern = "(\\w+)-(\\d+)\\*";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(template);
while(m.find())
{
System.out.println(m.group(1) + " " + m.group(2));
}
To explain this a bit more, "(\\w+)-(\\d+)\\*" looks for a (\\w+), which is any set of at least 1 character from [A-Za-z0-9_], followed by a -, followed by a number \\d+, where the+ means at least one character in length, followed by a *, which must be escaped. The parentheses capture what's inside of them. There are two sets of capturing parentheses in this regex, so we reference them by group(1) and group(2) as seen in the while loop, which prints:
Pizza 1
Nutella 20
Chicken 65

Related

Get string inside string

So I have this string:
String myString = "Welcome, your drive today to the LAX will be (45+ min). Enjoy your drive!";
What is the best way to go about getting the 45 as a separate string? And this string could sometimes have more than one number in it, Example:
String myString = "Welcome, your drive today to the LAX will be (45+ min). You should arrive about (11:10 am). Enjoy your drive!";
But I only want to get the one what has 45+ min and separate out the + min so that 45 is my only string.
This can be easily done using regular expressions.
Java Predefined character classes for regular expressions.
. = Any character (may or may not match line terminators)
\d = A digit: [0-9]
\D = A non-digit: [^0-9]
String myString = "Welcome, your drive today to the LAX will be (45+ min). Enjoy your drive!";
//Replace all non digit characters with empty space so only numbers will be there.
myString = myString.replaceAll("\\D", "");
System.out.println(myString); //this displays only numbers.
So I did figure out my answer after a lot of trial and error. If you have a better way please comment it, I don't mind changing my accepted answer.
String text = "Welcome, your drive today to the LAX will be (45+ min) and the tolls will cost ($2.50). Enjoy your drive!";
tripMiles = getNumberFromString("(?i)(\\d+)\\s+ min", text);
public static double getNumberFromString(String value, final String s)
{
double n = 0.0;
Matcher M = Pattern.compile(value).matcher(s);
while (((Matcher)M).find())
{
try {
n = Double.parseDouble(((Matcher)M).group(1));
if (debug) Log.v(TAG, "Number is : " + ((Matcher)M).group(1));
}
catch (Exception ex) {
n = 0.0;
}
}
return n;
}

Regex pattern to convert comma separated String

Changing string with comma separated values to numbered new-line values
For example:
Input: a,b,c
Output:
1.a
2.b
3.c
Finding it hard to change it using regex pattern, instead of converting string to string array and looping through.
I'm not really sure, that it's possible to achive with only regex without any kind of a loop. As fore me, the solution with spliting the string into an array and iterating over it, is the most straightforward:
String value = "a,b,c";
String[] values = value.split(",");
String result = "";
for (int i=1; i<=values.length; i++) {
result += i + "." + values[i-1] + "\n";
}
Sure, it's possible to do without splitting and any kind of arrays, but it could be a little bit awkward solution, like:
String value = "a,b,c";
Pattern pattern = Pattern.compile("[(^\\w+)]");
Matcher matcher = pattern.matcher(value.replaceAll("\\,", "\n"));
StringBuffer s = new StringBuffer();
int i = 0;
while (matcher.find()) {
matcher.appendReplacement(s, ++i + "." + matcher.group());
}
System.out.println(s.toString());
Here the , sign is replaced with \n new line symbol and then we are looking for a groups of characters at the start of every line [(^\\w+)]. If any group is found, then we are appending to the start of this group a line number. But even here we have to use a loop to set the line number. And this logic is not as clear, as the first one.

Parsing a string with [3:0] substring in it

I want to store two numbers from a string into two distinct variables - for example, var1 = 3 and var2 = 0 from "[3:0]". I have the following code snippet:
String myStr = "[3:0]";
if (myStr.trim().matches("\\[(\\d+)\\]")) {
// Do something.
// If it enter the here, here I want to store 3 and 0 in different variables or an array
}
Is it possible doing this with split and regular expressions?
Don't call trim(). Enhance you regex instead.
Your regex is missing the pattern for : and the second number, and you don't need to escape the ].
To capture the matched numbers, you need the Matcher:
String myStr = " [3:0] ";
Matcher m = Pattern.compile("\\s*\\[(\\d+):(\\d+)]\\s*").matcher(myStr);
if (m.matches())
System.out.println(m.group(1) + ", " + m.group(2));
Output
3, 0
You can use replaceAll and split
String myStr = "[3:0]";
if(myStr.trim().matches("\\[\\d+:\\d+\\]") {
String[] numbers = myStr.replaceAll("[\\[\\]]","").split(":");
}
Moreover, your regExp to match String should be \\[\\d+:\\d+\\], if you want to avoid trim you can add \\s+ at start and end to match the spaces.But trim is not bad.
EDIT
As suggested by Andreas in comments,
String myStr = "[3:0]";
String regExp = "\\[(\\d+):(\\d+)\\]";
Pattern pattern = Pattern.compile(regExp);
Matcher matcher = pattern.matcher(myStr.trim());
if(matcher.find()) {
int a = Integer.parseInt(matcher.group(1));
int b = Integer.parseInt(matcher.group(2));
System.out.println(a + " : " + b);
}
OUTPUT
3 : 0
Without any regular expressions you could do this:
// this will remove the braces [ and ] and just leave "3:0"
String numberString= myString.trim().replace("[", "").replace("]","");
// this will split the string in everything before the : and everything after the : (so two values as an array)
String[] numbers = numberString.split(":");
// get the first value and parse it as a number "3" will become a simple 3
int firstNumber = Integer.parseInt(numbers[0]) ;
// get the second value and parse it from "0" to a plain 0
int secondNumber = Integer.parseInt(numbers[1]);
be carefull when parsing numbers, depending on your input string and what other possibilities there might be (e.g. "3:12" is ok, but "3:02" might throw an error).
In case you don't need to validate input and you want to simply get numbers from it, you could simply find indexOf(":") and substring parts which you are interested, in which are:
from [ (which is at position 0) till :
and from index of : till ] (which is at position equal to length of string -1)
Your code can look like
String text = "[3:0]";
int colonIndex = text.indexOf(':');
String first = text.substring(1, colonIndex);
String second = text.substring(colonIndex + 1, text.length() - 1);

How would I go about splitting a sentence in Java [duplicate]

This question already has answers here:
Wrap the string after a number of characters word-wise in Java
(6 answers)
Closed 8 years ago.
I am attempting to split a sentence that is being printed to the console in order to avoid cut offs like so # 80 chars:
Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave ad
venturer?
So I would like it to print like so
Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave
adventurer?
Is there a way to do this with String.split() ?
You can do something like this, where you decide whether to do a new line or not, depending on the lines current size:
public static String getLines(String line){
String[] words = line.split(" ");
StringBuilder str = new StringBuilder();
int size = 0;
for (int i = 0; i < words.length; i++) {
if(size==0){
str.append(words[i]);
}
if(size+words[i].length()+1<=80){
str.append(" ").append(words[i]);
size++;
}else{
str.append("\n").append(words[i]);
size = 0;
}
size+=words[i].length();
}
return str.toString();
}
Another different way of doing the same:
public static String getLines2(String line){
StringBuilder str = new StringBuilder();
int begin = 0;
while(begin<line.length()){
int lineEnd = Math.min(begin + 80, line.length());
while(lineEnd<line.length()&&line.charAt(lineEnd)!= ' '){
lineEnd--;
}
str.append(line.subSequence(begin, lineEnd));
if(lineEnd<line.length()) str.append("\n");
begin = lineEnd+1;
}
return str.toString();
}
Depending on how exact it has to be, Regex can do this pretty well. If you just need to split at spaces, a simple
String eg = "Example sentence with, some. spaces! and stuff";
String[] splitSentence = eg.split(" ");
will do the job, splitting the string at every space and thus returning the words with their adjacent special characters as a String array. You could then simply add up the characters (with the spaces inbetween) and if you pass your border (in your case 80), pop the last word and add a '\n':
String getConsoleFormattedString(String s, int rowLength) {
String[] split = s.split(" ");
String ret = "";
int counter = 0,
for(int i = 0; i < split.length; i++) {
if(counter + split[i] + 1 <= 80)
ret += split[i] + " ";
else {
ret += "\n";
counter = 0;
i--;
}
}
return ret;
}
I will let you figure out how to handle words with > 80 letters, for the sake of simplicity
split is not best option here, but you can use Pattern and Matcher classes with this regex
\\G.{1,80}(\\s+|$)
which means
\\G place of last match, or if it is first iteration of searching for match (so there was not any yet) start of the string (represented by ^)
.{1,80} any characters can appear between one and eighty times
(\\s+|$) one or more whitespaces or end of string
You can use it this way
String data = "Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave "
+ "adventurer? ";
Pattern p = Pattern.compile("\\G.{1,80}(\\s+|$)");
Matcher m = p.matcher(data);
while(m.find())
System.out.println(m.group().trim());
Output:
Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave
adventurer?
But assuming that you can face with very long words which shouldn't be split you can add
\\S{80,}
to your regex to also let it find non-whitespace strings which length is 80 or more.
Example:
String data = "Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave "
+ "adventurer? foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar";
Pattern p = Pattern.compile("\\G.{1,80}(\\s+|$)|\\S{80,}");
Matcher m = p.matcher(data);
while (m.find())
System.out.println(m.group().trim());
Output:
Welcome to fancy! A text based rpg. Perhaps you could tell us your name brave
adventurer?
foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar-foo-bar

String tokenizer to token a phone number

Can you help me tokenize a user input for a phone number in the following format: xxx xxx-xxxx in the first else if
The regular expression has been validated to work correctly. I will include it.
To follow the same procedure i have with the rest of the phone numbers i want to grab
the first 3 digits into a seperate variable and the rest to concatenate.
Here is the code
else if (ValidatePhone.validateSpaceAfterAreaCode(input)) {
StringTokenizer st = new StringTokenizer(input);
String token = st.nextToken("\\s").toString();
// firstdigits = new Long(st.nextToken("\\s")).toString();
phoneNumber = new Long(st.nextToken("-")).toString();
phoneNumber += new Long(st.nextToken("-")).toString();
num = Long.parseLong(phoneNumber);
JOptionPane.showMessageDialog(null, "first digits: " + token + "\nlast digits: " + num);
}
//WORKING for xxx.xxx.xxxx
else if (ValidatePhone.validateAllPeriods(input)) {
StringTokenizer st = new StringTokenizer(input);
firstdigits = new Long(st.nextToken(".")).toString();
phoneNumber = new Long(st.nextToken(".")).toString();
phoneNumber += new Long(st.nextToken(".")).toString();
num = Long.parseLong(phoneNumber);
JOptionPane.showMessageDialog(null, "first digits: " + firstdigits + "\nlast digits: " + num);
}
here is the function in the validate phone class
public static boolean validateSpaceAfterAreaCode(String acspace)
{
return acspace.matches("^[1-9]\\d{2}\\s\\d{3}-\\d{4}");
}
You are making this much more complex than it needs to be. I'm guessing the allowable forms are
nnn nnn-nnnn
nnn-nnn-nnnn
nnn.nnn.nnnn
and that you don't want to allow other variations such as nnn nnn.nnnn or nnn.nnn-nnnn. Try this
Pattern p1 = Pattern.compile("([2-9]\\d{2})([-.])(\\d{3})\\2(\\d{4})");
Pattern p2 = Pattern.compile("([2-9]\\d{2})(\\s)(\\d{3})-(\\d{4})");
Matcher m = p1.matcher(input);
if (!m.matches())
m = p2.matcher(input)
if (m.matches()
{
// results are in m.group(1), m.group(3) and m.group(4)
}
else
{
// input didn't match
}
Explanation:
p1
([2-9]\\d{2}) - Areacode (first digit must be 2-9)
([-.]) - Delimiter, either a dot or hyphen
(\\d{3}) - The 3-digit exchange
\\2 - Back-reference to the first delimiter
(\\d{4}) - The 4-digit number
The back-reference causes the regex to match whatever the first delimiter matched.
Pattern p2 is simple except I put capturing parentheses around the first delimiter so the indexes of the numeric groups would be the same in both cases, eliminating the need to check which pattern matched.
I would just split it:
String parts = input.split("\\D+");
This splits using any sequence of non-digits and will create an array of size 3, which you can then parse into ints etc.

Categories