For the code i need to write a method the decompresses a string. For example if the user entered "2d5t" the method would return "ddttttt". My code now will work for that input but if the input uses a character without a number before it the program wont work when it should. For example if the input was just "d" the program wouldnt work instead of just returning "d". The code also has to be recursive.
Here is what my code is now please help.
public static String decompress(String compressedText) {
if (compressedText.equals(""))
return "";
return decompress(compressedText, charInt(compressedText, 0), 0);
}
public static String decompress(String text, int count, int pos) {
if (pos == text.length() || (pos == text.length()-2 && count == 0))
return "";
else if (count == 0)
return decompress(text, charInt(text, pos+2), pos+2);
return text.charAt(pos+1) + decompress(text, count-1, pos);
}
public static int charInt(String str, int idex) {
return str.charAt(idex) - '0';
}
Here's some pseudocode:
function createString(int times, char character){
if times is 0, do nothing
otherwise return character + createString(times-1, character);
}
function createString(string full){
split string by number/character pairs
for each pair, call createString(times, character), and append them
}
I don't believe in handing out real code, sorry. It's much better in the long run.
You need to validate your user input. Decide first, that what string values are acceptable to your method and then write a validate method. Then invoke that method inside your decompress method.
Look into string manipulation functions and regular expressions in Java. And then try rewriting your code.
As mentioned by others, this can be solved with regular expressions. An example solution is:
public static String decompress(String compressed) {
Matcher matcher = Pattern.compile("(\\d+)([^\\d])").matcher(compressed);
StringBuffer decompressed = new StringBuffer();
while (matcher.find()) {
Integer charNum = Integer.parseInt(matcher.group(1));
StringBuilder decompressedChars = new StringBuilder();
for (int i = 1; i <= charNum; i++) {
decompressedChars.append(matcher.group(2));
}
matcher.appendReplacement(decompressed, decompressedChars.toString());
}
matcher.appendTail(decompressed);
return decompressed.toString();
}
This code won't support numbers larger than Integer.MAX_VALUE and you might want to put some error handling and validation in there also.
**Edited to be recursive as per the OP's request
Tested left first one char lookahead parser using regex
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Parser{
private static String parse(StringBuilder output, String input, Integer offset){
if(offset<input.length()){
java.util.regex.Pattern p0 =
java.util.regex.Pattern.compile("\\d(?=[a-z])");
java.util.regex.Pattern p1 =
java.util.regex.Pattern.compile("[a-z]");
java.util.regex.Matcher m0 = p0.matcher(input);
java.util.regex.Matcher m1 = p1.matcher(input);
if (m0.find(offset) && m0.start() == offset)
{
for(Integer i = 0;
i < Integer.parseInt(String.valueOf(input.charAt(offset)));
++i) {
output.append(input.charAt(offset+1));
}
offset+=2;
}
else if (m1.find(offset) && m1.start() == offset) {
output.append(input.charAt(offset));
++offset;
}
else {
++offset;
}
return parse(output, input, offset);
}
else return output.toString();
}
public static void main(String[] args)
{
Integer offset = 0;
StringBuilder output = new StringBuilder();
parse(output, args[0], offset);
System.out.println(output.toString());
}
}
Related
I have a method that extracts a certain substring from a string. This substring consists of the numbers in the string. Then this is parsed to an integer.
Method:
protected int startIndex() throws Exception {
String str = getWorkBook().getDefinedName("XYZ");
String sStr = str.substring(10,13);
return Integer.parseInt(sStr) - 1;
}
Example:
String :
'0 DB'!$B$460
subString :
460
Well, I manually entered the index range for the substring. But I would like to automate it.
My approach:
String str = getWorkBook().getDefinedName("XYZ");
int length = str.length();
String sStr = str.substring(length - 3, length);
This works well for this example.
Now there is the problem that the numbers at the end of the string can also be 4 or 5 digits. If that is the case, I naturally get a NullPointerException.
Is there a way or another approach to find out how many numbers are at the end of the string?
You can use the regex, (?<=\D)\d+$ which means one or more digits (i.e. \d+) from the end of the string, preceded by non-digits (i.e. \D).
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(getNumber("'0 DB'!$B$460"));
}
static String getNumber(String str) {
Matcher matcher = Pattern.compile("(?<=\\D)\\d+$").matcher(str);
if (matcher.find()) {
return matcher.group();
}
// If no match is found, return the string itself
return str;
}
}
In your case I would recommend to use regex with replaceAll like this:
String sStr = str.replaceAll(".*?([0-9]+)$", "$1");
This will extract the all the digits in the end or your String or any length.
Also I think you are missing the case when there are no digit in your String, for that I would recommend to check your string before you convert it to an Integer.
String sStr = str.replaceAll(".*?([0-9]+)$", "$1");
if (!sStr.isEmpty()) {
return Integer.parseInt(sStr) - 1;
}
return 0; // or any default value
If you just want to get the last number, you can go through the entire string on revert and get the start index:
protected static int startIndex() {
String str = getWorkBook().getDefinedName("XYZ");
if(Character.isDigit(str.charAt(str.length() - 1))) {
for(int i = str.length() - 1; i >= 0; i--){
if(!Character.isDigit(str.charAt(i)))
return i+1;
}
}
return -1;
}
and then print it:
public static void main(String[] args) {
int start = startIndex();
if(start != -1)
System.out.println(getWorkBook().getDefinedName("XYZ").substring(start));
else
System.out.println("No Number found");
}
You will have to add the
Simple and fast solution without RegEx:
public class Main
{
public static int getLastNumber(String str) {
int index = str.length() - 1;
while (index > 0 && Character.isDigit(str.charAt(index)))
index--;
return Integer.parseInt(str.substring(index + 1));
}
public static void main(String[] args) {
final String text = "'0 DB'!$B$460";
System.out.println(getLastNumber(text));
}
}
The output will be:
460
If I were going to do this I just search from the end. This is quite efficient. It returns -1 if no positive number is found. Other return options and the use of an OptionalInt could also be used.
String s = "'0 DB'!$B$460";
int i;
for (i = s.length(); i > 0 && Character.isDigit(s.charAt(i-1)); i--);
int vv = (i < s.length()) ? Integer.valueOf(s.substring(i)) : -1;
System.out.println(vv);
Prints
460
If you know that there will always be a number at the end you can forget the ternary (?:) above and just do the following:
int vv = Integer.valueOf(s.substring(i));
I have the reg ex \\(.*?\\) to match what ever inside the parenthesis from my text
e.g. ((a=2 and age IN (15,18,56)) and (b=3 and c=4))
my output should only contain:
a=2 and age IN (15,18,56)
b=3 and c=4
I have tried using negative lookahead, not to match .*(?!IN)\\(.*?\\) but not returning what I expect. Can any body help with where I am going wrong?
You will need to parse nested expressions, and regular expressions alone cannot do that for you. A regular expression will only catch the innermost expressions with \\(([^(]*?)\\)
You can use the Pattern and Matcher classes to code a more complex solution.
Or you can use a parser. For Java, there's ANTL.
I just coded something that might help you:
public class NestedParser {
private final char opening;
private final char closing;
private String str;
private List<String> matches;
private int matchFrom(int beginIndex, boolean matchClosing) {
int i = beginIndex;
while (i < str.length()) {
if (str.charAt(i) == opening) {
i = matchFrom(i + 1, true);
if (i < 0) {
return i;
}
} else if (matchClosing && str.charAt(i) == closing) {
matches.add(str.substring(beginIndex, i));
return i + 1;
} else {
i++;
}
}
return -1;
}
public NestedParser(char opening, char closing) {
this.opening = opening;
this.closing = closing;
}
public List<String> match(String str) {
matches = new ArrayList<>();
if (str != null) {
this.str = str;
matchFrom(0, false);
}
return matches;
}
public static void main(String[] args) {
NestedParser parser = new NestedParser('(', ')');
System.out.println(parser.match(
"((a=2 and age IN (15,18,56)) and (b=3 and c=4))"));
}
}
It's not clear what you want in terms of nested brackets (eg. ((a = 2 and b = 3)): is this valid or not?)
This regex gets you most of the way there:
(\(.*?\)+)
On the input you specified, it matches two groups:
((a=2 and age IN (15,18,56))
(b=3 and c=4)) (notice the double-bracket at the end).
It will return everything, including nested brackets. Another variation will return only singly-bracketed expressions:
(\([^(]*?\))
The easiest way to test this is through Rubular.
The idea is to have a String read and to verify that it does not contain any numeric characters. So something like "smith23" would not be acceptable.
What do you want? Speed or simplicity? For speed, go for a loop based approach. For simplicity, go for a one liner RegEx based approach.
Speed
public boolean isAlpha(String name) {
char[] chars = name.toCharArray();
for (char c : chars) {
if(!Character.isLetter(c)) {
return false;
}
}
return true;
}
Simplicity
public boolean isAlpha(String name) {
return name.matches("[a-zA-Z]+");
}
Java 8 lambda expressions. Both fast and simple.
boolean allLetters = someString.chars().allMatch(Character::isLetter);
Or if you are using Apache Commons, [StringUtils.isAlpha()].
First import Pattern :
import java.util.regex.Pattern;
Then use this simple code:
String s = "smith23";
if (Pattern.matches("[a-zA-Z]+",s)) {
// Do something
System.out.println("Yes, string contains letters only");
}else{
System.out.println("Nope, Other characters detected");
}
This will output:
Nope, Other characters detected
I used this regex expression (".*[a-zA-Z]+.*"). With if not statement it will avoid all expressions that have a letter before, at the end or between any type of other character.
String strWithLetters = "123AZ456";
if(! Pattern.matches(".*[a-zA-Z]+.*", str1))
return true;
else return false
A quick way to do it is by:
public boolean isStringAlpha(String aString) {
int charCount = 0;
String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if (aString.length() == 0) {
return false; //zero length string ain't alpha
}
for (int i = 0; i < aString.length(); i++) {
for (int j = 0; j < alphabet.length(); j++) {
if (aString.substring(i, i + 1).equals(alphabet.substring(j, j + 1))
|| aString.substring(i, i + 1).equals(alphabet.substring(j, j + 1).toLowerCase())) {
charCount++;
}
}
if (charCount != (i + 1)) {
System.out.println("\n**Invalid input! Enter alpha values**\n");
return false;
}
}
return true;
}
Because you don't have to run the whole aString to check if it isn't an alpha String.
private boolean isOnlyLetters(String s){
char c=' ';
boolean isGood=false, safe=isGood;
int failCount=0;
for(int i=0;i<s.length();i++){
c = s.charAt(i);
if(Character.isLetter(c))
isGood=true;
else{
isGood=false;
failCount+=1;
}
}
if(failCount==0 && s.length()>0)
safe=true;
else
safe=false;
return safe;
}
I know it's a bit crowded. I was using it with my program and felt the desire to share it with people. It can tell if any character in a string is not a letter or not. Use it if you want something easy to clarify and look back on.
Faster way is below. Considering letters are only a-z,A-Z.
public static void main( String[] args ){
System.out.println(bestWay("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(isAlpha("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(bestWay("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
System.out.println(isAlpha("azAZpratiyushkumarsinghjdnfkjsaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
}
public static boolean bettertWay(String name) {
char[] chars = name.toCharArray();
long startTimeOne = System.nanoTime();
for(char c : chars){
if(!(c>=65 && c<=90)&&!(c>=97 && c<=122) ){
System.out.println(System.nanoTime() - startTimeOne);
return false;
}
}
System.out.println(System.nanoTime() - startTimeOne);
return true;
}
public static boolean isAlpha(String name) {
char[] chars = name.toCharArray();
long startTimeOne = System.nanoTime();
for (char c : chars) {
if(!Character.isLetter(c)) {
System.out.println(System.nanoTime() - startTimeOne);
return false;
}
}
System.out.println(System.nanoTime() - startTimeOne);
return true;
}
Runtime is calculated in nano seconds. It may vary system to system.
5748//bettertWay without numbers
true
89493 //isAlpha without numbers
true
3284 //bettertWay with numbers
false
22989 //isAlpha with numbers
false
Check this,i guess this is help you because it's work in my project so once you check this code
if(! Pattern.matches(".*[a-zA-Z]+.*[a-zA-Z]", str1))
{
String not contain only character;
}
else
{
String contain only character;
}
String expression = "^[a-zA-Z]*$";
CharSequence inputStr = str;
Pattern pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(inputStr);
if(matcher.matches())
{
//if pattern matches
}
else
{
//if pattern does not matches
}
Try using regular expressions: String.matches
public boolean isAlpha(String name)
{
String s=name.toLowerCase();
for(int i=0; i<s.length();i++)
{
if((s.charAt(i)>='a' && s.charAt(i)<='z'))
{
continue;
}
else
{
return false;
}
}
return true;
}
Feels as if our need is to find whether the character are only alphabets.
Here's how you can solve it-
Character.isAlphabetic(c)
helps to check if the characters of the string are alphabets or not.
where c is
char c = s.charAt(elementIndex);
While there are many ways to skin this cat, I prefer to wrap such code into reusable extension methods that make it trivial to do going forward. When using extension methods, you can also avoid RegEx as it is slower than a direct character check. I like using the extensions in the Extensions.cs NuGet package. It makes this check as simple as:
Add the https://www.nuget.org/packages/Extensions.cs package to your project.
Add "using Extensions;" to the top of your code.
"smith23".IsAlphabetic() will return False whereas "john smith".IsAlphabetic() will return True. By default the .IsAlphabetic() method ignores spaces, but it can also be overridden such that "john smith".IsAlphabetic(false) will return False since the space is not considered part of the alphabet.
Every other check in the rest of the code is simply MyString.IsAlphabetic().
To allow only ASCII letters, the character class \p{Alpha} can be used. (This is equivalent to [\p{Lower}\p{Upper}] or [a-zA-Z].)
boolean allLettersASCII = str.matches("\\p{Alpha}*");
For allowing all Unicode letters, use the character class \p{L} (or equivalently, \p{IsL}).
boolean allLettersUnicode = str.matches("\\p{L}*");
See the Pattern documentation.
I found an easy of way of checking a string whether all its digit is letter or not.
public static boolean isStringLetter(String input) {
boolean b = false;
for (int id = 0; id < input.length(); id++) {
if ('a' <= input.charAt(id) && input.charAt(id) <= 'z') {
b = true;
} else if ('A' <= input.charAt(id) && input.charAt(id) <= 'Z') {
b = true;
} else {
b = false;
}
}
return b;
}
I hope it could help anyone who is looking for such method.
Use StringUtils.isAlpha() method and it will make your life simple.
I have been messing around with recursion today. Often a programming technique that is not used enough.
I set out to recursively reverse a string. Here's what I came up with:
//A method to reverse a string using recursion
public String reverseString(String s){
char c = s.charAt(s.length()-1);
if(s.length() == 1) return Character.toString(c);
return c + reverseString(s.substring(0,s.length()-1));
}
My question: is there a better way in Java?
The best way is not to use recursion. These stuff are usually used to teach students the recursion concept, not actual best practices. So the way you're doing it is just fine. Just don't use recursion in Java for these kind of stuff in real world apps ;)
PS. Aside what I just said, I'd choose "" as the base case of my recursive function:
public String reverseString(String s){
if (s.length() == 0)
return s;
return reverseString(s.substring(1)) + s.charAt(0);
}
If you're going to do this, you want to operate on a character array, because a String is immutable and you're going to be copying Strings all over the place if you do it that way.
This is untested and totally stream of consciousness. It probably has an OB1 somewhere. And very not-Java.
public String reverseString(String s)
{
char[] cstr = s.getChars();
reverseCStr(cstr, 0, s.length - 1);
return new String(cstr);
}
/**
* Reverse a character array in place.
*/
private void reverseCStr(char[] a, int s, int e)
{
// This is the middle of the array; we're done.
if (e - s <= 0)
return;
char t = a[s];
a[s] = a[e];
a[e] = t;
reverseCStr(a, s + 1, e - 1);
}
You don't want to nest too deeply. Divide-and-conquer is the way to go. Also reduces total size of temporary strings and is amenable to parallelisation.
public static String reverseString(String str) {
int len = str.length();
return len<=1 ? str : (
reverseString(str.substring(len/2))+
reverseString(str.substring(0, len/2))
);
}
(Not tested - this is stackoverflow.)
String.concat instead of + would improve performance at the expense of clarity.
Edit: Just for fun, a tail-recursion friendly version of the naive algorithm.
public static String reverseString(String str) {
return reverseString("", str);
}
private static String reverseString(String reversed, String forward) {
return forward.equals("") ? reversed : (
reverseString(reversed+forward.charAt(0), forward.substring(1))
);
}
Correct handling of surrogate pairs is left to the interested reader.
here is my recursive reverse function that is working fine
public static String rev(String instr){
if(instr.length()<=1){
return instr;
} else {
return (instr.charAt(instr.length()-1)+rev(instr.substring(0,instr.length()-1)) );
}
}
Just for the heck of it, here's a tail-recursive method using StringBuilder (which is generally recommended over manipulating Strings).
public String reverseString(String s_) {
StringBuilder r = new StringBuilder();
StringBuilder s = new StringBuilder(s_);
r = reverseStringHelper(r, s);
return r.toString();
}
private StringBuilder reverseStringHelper(StringBuilder r, StringBuilder s) {
if (s.length() == 0)
return r;
else
return reverseStringHelper(r.append(s.charAt(0)), s.deleteCharAt(0));
}
Untested, I haven't dealt with Java in many years, but this should be about right.
If you're writing real code (not learning recursion), use StringBuilder's reverse() method. The Java Tutorial gives this example:
String palindrome = "Dot saw I was Tod";
StringBuilder sb = new StringBuilder(palindrome);
sb.reverse(); // reverse it
System.out.println(sb);
It depends on what you define as "better". :-) Seriously, though; your solution essentially uses the maximum depth of recursion; if stack size is of a concern for your definition of "better", then you'd be better off using something like this:
public String reverseString(String s) {
if (s.length() == 1) return s;
return reverseString(s.substring(s.length() / 2, s.length() -1) + reverseString(0, s.length() / 2);
}
This is what I've found to work and use recursive. You can pass str.length() as strLength argument
private static String reverse(String str, int strLength) {
String result = "";
if(strLength > 0)
result = str.charAt(strLength - 1) + reverse(str, strLength - 1);
return result;
}
In Java, since the String is immutable, the String concatenation would be more complex than it looks like.
For every concatenation, it creates a new string copying the contents of original String resulting in a linear complexity O(n) where n is the length of the string, so for m such operations it is O(m*n), we can say it is of quadratic complexity O(n^2).
We can use a StringBuilder which has O(1) complexity for each append. Below is the recursive program using StringBuilder. This uses only n/2 stack frames, so it has less space complexity than the normal recursive call which would be like s.charAt(s.length-1) + reverse(s.subString(0, s.length-2);
public class StringReverseRecursive {
public static void main(String[] args) {
String s = "lasrever gnirts fo noitatnemelpmi evisrucer a si sihT";
StringBuilder sb = new StringBuilder(s);
reverse(s, sb, 0, sb.length() - 1);
System.out.println(sb.toString());
}
public static void reverse(String s, StringBuilder sb, int low, int high) {
if (low > high)
return;
sb.setCharAt(low, s.charAt(high));
sb.setCharAt(high, s.charAt(low));
reverse(s, sb, ++low, --high);
}
}
That's definitely how I'd go about recursively reversing a string (although it might be nice to extend it to the case of an empty string in your condition.) I don't think there is any fundamentally better way.
EDIT: It may be more efficient to operate on a character array and pass a "cutoff" length down the chain of recursion, if you get my drift, rather than making substrings. However, this is not really worth nitpicking about, since it's not a terribly efficient technique in the first place.
You capture the basic idea, but extracting the last character doesn't improve clarity. I'd prefer the following, others might not:
public class Foo
{
public static void main(String[] argv) throws Exception
{
System.out.println(reverse("a"));
System.out.println(reverse("ab"));
System.out.println(reverse("abc"));
}
public final static String reverse(String s)
{
// oft-repeated call, so reduce clutter with var
int length = s.length();
if (length <= 1)
return s;
else
return s.substring(length - 1) + reverse(s.substring(0, length - 1));
}
}
As Mehrdad noted, it's best not to use recursion. If you do use it, though, you might as well keep both the first and last character each call, thus halving the number of recursive calls. That is,
public String reverseString(String s){
int len = s.length();
if (len <= 1) {
return s;
}
char fst = s.charAt(0);
char lst = s.charAt(len - 1);
return lst + reverseString(s.substring(1, len - 2)) + fst;
}
This also handles the case of the empty string. Perhaps passing along a StringBuilder with the appropriate capacity would speed things up even more, but that's left as an exercise to the reader ;)
You can try with an external variable, and add 1 by 1 all chars:
public static String back="";
public static String reverseString(String str){
if(str.length()==0){
return back;
}else {
back+=str.charAt(str.length()-1);
lees(str.substring(0,str.length()-1));
return back;
}
}
Here is my immutable version:
String reverse(String str) {
if(str.length()<2) return str;
return reverse(str.substring(1)) +str.charAt(0);
}
and tail recursive version:
String reverseTail(String str) {
if(str.length()<2) return str;
return str.charAt(str.length()-1)+ reverseTail(str.substring(0,str.length()-1));
In this context, this is totally unnecessary, but you can simulate recursion and avoid recursion depth issues if you make your own stack.
You can iterative implement recursion, which may be necessary when you have algorithms which are inherently recursive, but also need to run them for big problem sizes.
String recIterReverse (String word){
Stack <String> stack = new Stack <String> ();
stack.push(word);
String result = "";
while (!stack.isEmpty()){
String temp = stack.pop();
result = temp.charAt(0) + result;
if (temp.length() > 1){
stack.push(temp.substring(1));
}
}
return result;
}
function call:
//str:string to be reversed,i=0,j=str.length-1
public void reverseString(String str,int i,int j)
{
if(i==j)
{
System.out.println(str);
return;
}
char x=str.charAt(i);
str=str.replace(str.charAt(i),str.charAt(j));
str=str.replace(str.charAt(j),x);
i++;j--;
reverseString(str,i,j);
}
this method works too..
Try the following:
public class reverse2
{
public static void main(String name)
{
String revname=new StringBuffer(name).reverse().toString();
System.out.println("original string " + name + " and the reverse of it is " + revname);
}
}
public static String rev(String name){
if(name.length()>=1){
System.out.print(name.charAt(name.length()-1));
return rev(name.substring(0,name.length()-1));
}
else{
return ""+name.substring(0);
}
}
String rev="";
public String reverseString(String s){
if (s.length()==0) return "";
return rev+s.substring(s.length()-1,s.length())+reverseString(s.substring(0, s.length()-1));
}
public String reverseString (String s) {
if (s != null && s.length () > 0 ) {
rev = rev + s.substring (s.length () - 1);
reverseString (s.substring (0, s.length () - 1));
}
return rev;
}
public class StringUtility {
public static void main(String[] args) {
StringUtility stringUtility = new StringUtility();
String input = "santosh123";
int middle = input.length() / 2;
middle = middle - 1;
System.out.println(stringUtility.stringReverse(input, middle));
}
public String stringReverse(String input, int middle) {
if (middle == -1) {
System.out.println("if");
return input;
} else {
System.out.println("else");
input = swapChar(input, middle);
middle = middle - 1;
return stringReverse(input, middle);
}
}
private String swapChar(String input, int middle) {
StringBuilder str = new StringBuilder(input);
char begin = str.charAt(middle);
int endIndex = input.length() - middle - 1;
char end = str.charAt(endIndex);
str.setCharAt(middle, end);
str.setCharAt(endIndex, begin);
System.out.println(str + " " + middle + " " + endIndex);
return str.toString();
}
}
If you think less code is good then....
static String reverse(String str){
return str.length()>=2 ? str.charAt(str.length()-1) + reverse(str.substring(0,str.length()-1)) : str ;
}
There are about 20 answers already but I'll just throw in my recursive algorithm as well. It may be a little verbose but it is at least readable.
public static String reverseString(String str) {
return reverseString("", str);
}
private static String reverseString(String result, String original) {
if (original.length() == 0) {
return result;
} else {
int length = original.length();
String lastLetter = original.substring(length - 1, length);
original = original.substring(0, length - 1);
return reverseString(result + lastLetter, original);
}
}
The code basically recursively takes the end of the string and moves it in front. For example if the string we want to reverse is "jam," then each time the helper method is called, result and original strings are as follows:
// result: original:
// "" jam
// m ja
// ma j
// maj ""
Reverse String using the recursive method call.
Sample Code
public static String reverseString(String s) {
if (s.length() == 0) {
return s;
}
else {
return s.charAt(s.length() - 1) + reverseString(s.substring(0, s.length() - 1));
}
}
This is my solution,I saw in many solutions above we are getting the string length but ideally we don't need that. The Zen is to use recursion, just chop the first char of string and pass the rest to recursive method. Yay!! we got the solution.
private static void printReverse(String str) {
if (!str.isEmpty()) {
String firstChar = str.substring(0, 1); //Get first char of String
String newstr = str.substring(0, 0) + str.substring(1); // Get remaining string
printReverse(newstr); // Recursion magic
System.out.print(firstChar); //Output
}
}
public static String reverse(String s){
int n = s.length()-1;
if(n >=0)
return s.substring(s.length()-1)+ReverseString(s.substring(0,n--));
else return "";
}
How do I split strings in J2ME in an effective way?
There is a StringTokenizer or String.split(String regex) in the standard edition (J2SE), but they are absent in the micro edition (J2ME, MIDP).
There are a few implementations of a StringTokenizer class for J2ME. This one by Ostermiller will most likely include the functionality you need
See also this page on Mobile Programming Pit Stop for some modifications and the following example:
String firstToken;
StringTokenizer tok;
tok = new StringTokenizer("some|random|data","|");
firstToken= tok.nextToken();
There is no built in method to split strings. You have to write it on your own using
String.indexOf() and String.substring(). Not hard.
String.split(...) is available in J2SE, but not J2ME.
You are required to write your own algorithm: related post with sample solution.
I hope this one will help you... This is my own implementation i used in my application. Of course this can still be optimized. i just do not have time to do it... and also, I am working on StringBuffer here. Just refactor this to be able to use String instead.
public static String[] split(StringBuffer sb, String splitter){
String[] strs = new String[sb.length()];
int splitterLength = splitter.length();
int initialIndex = 0;
int indexOfSplitter = indexOf(sb, splitter, initialIndex);
int count = 0;
if(-1==indexOfSplitter) return new String[]{sb.toString()};
while(-1!=indexOfSplitter){
char[] chars = new char[indexOfSplitter-initialIndex];
sb.getChars(initialIndex, indexOfSplitter, chars, 0);
initialIndex = indexOfSplitter+splitterLength;
indexOfSplitter = indexOf(sb, splitter, indexOfSplitter+1);
strs[count] = new String(chars);
count++;
}
// get the remaining chars.
if(initialIndex+splitterLength<=sb.length()){
char[] chars = new char[sb.length()-initialIndex];
sb.getChars(initialIndex, sb.length(), chars, 0);
strs[count] = new String(chars);
count++;
}
String[] result = new String[count];
for(int i = 0; i<count; i++){
result[i] = strs[i];
}
return result;
}
public static int indexOf(StringBuffer sb, String str, int start){
int index = -1;
if((start>=sb.length() || start<-1) || str.length()<=0) return index;
char[] tofind = str.toCharArray();
outer: for(;start<sb.length(); start++){
char c = sb.charAt(start);
if(c==tofind[0]){
if(1==tofind.length) return start;
inner: for(int i = 1; i<tofind.length;i++){ // start on the 2nd character
char find = tofind[i];
int currentSourceIndex = start+i;
if(currentSourceIndex<sb.length()){
char source = sb.charAt(start+i);
if(find==source){
if(i==tofind.length-1){
return start;
}
continue inner;
} else {
start++;
continue outer;
}
} else {
return -1;
}
}
}
}
return index;
}
That depends on what exactly you want to achieve, but the function String.substring() will be in there somewhere:
String myString = "Hello World";
This will print the substring starting from index 6 to the end of the string:
System.out.println(myString.substring(6));
This will print the substring starting from index 0 until index 5:
System.out.println(myString.substring(0,5));
Output of all the code above:
World
Hello
Combine this with the other String functions (indexOf(). etc.) to achieve the desired effect!
Re-reading your question, it looks as though you may have been looking for String.split(). This will split your input string into an array of strings based on a given regex:
String myString = "Hi-There-Gang";
String[] splitStrings = myString.split("-");
This will result in the splitStrings array containing three string, "Hi", "There" and "Gang".
Re-reading your question again, String.split is not available in J2ME, but the same effect can be achieved with substring and indexOf.
public static Vector splitDelimiter(String text, char delimiter) {
Vector splittedString = null;
String text1 = "";
if (text != null) {
splittedString = new Vector();
for (int i = 0; i < text.length(); i++) {
if (text.charAt(i) == delimiter) {
splittedString.addElement(text1);
text1 = "";
} else {
text1 += text.charAt(i);
// if(i==text.length()-1){
// splittedString.addElement(text1);
// }
}
}
splittedString.addElement(text1);
}
return s
}
You can use this method for splitting a delimiter.
In J2ME no split, but you can use this code for split.This code works with only 1 simbol delimiter!!!
Use NetBeans.File\Create Project\ Java ME\ MobileApplication\Set project name(split)\Set checkmark.Delete all code in your (Midlet.java).Copy this code and past in your (Midlet.java).
//IDE NetBeans 7.3.1
//author: UserSuperPupsik
//email: usersuperpupsik#gmail.com
package split;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import java.util.Vector;
public class Midlet extends MIDlet {
public String e1;
public Vector v=new Vector();
public int ma;
int IsD=0;
int vax=0;
public String out[];
private Form f;
public void split0(String text,String delimiter){
if (text!=""){
IsD=0;
int raz=0;
//v.removeAllElements();
v.setSize(0);
int io;
String temp="";
int ni=(text.length()-1);
for(io=0;io<=ni;io++){
char ch=text.charAt(io);
String st=""+ch;
if(io==0 && st.equals(delimiter)){IsD=1;}
if(!st.equals(delimiter)){temp=temp+st;} //Not equals (!=)
else if(st.equals(delimiter)&&temp!="")//equals (==)
{
IsD=1;
//f.append(temp);
v.addElement(temp);
temp="";
}
if(io==ni && temp!="") {
v.addElement(temp);
temp="";
}
if((io==ni)&&IsD==0&&temp!=""){v.addElement(temp);}
}
if(v.size()!=0){
ma=(v.size());
out=new String[ma];
v.copyInto(out);
}
//else if(v.size()==0){IsD=1; }
}
}
public void method1(){
f.append("\n");
f.append("IsD: " +IsD+"");
if (v.size()!=0){
for( vax=0;vax<=ma-1;vax++){
f.append("\n");
f.append(out[vax]);
}
}
}
public void startApp() {
f=new Form("Hello J2ME!");
Display.getDisplay(this).setCurrent(f);
f.append("");
split0("Hello.World.Good...Luck.end" , ".");
method1();
split0(".",".");
method1();
split0(" First WORD2 Word3 "," ");
method1();
split0("...",".");
method1();
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
Splited elements located in array called (out).For Example out[1]:Hello.
Good Luck!!!
Another alternative solution:
public static Vector split(String stringToSplit, String separator){
if(stringToSplit.length<1){
return null;
}
Vector stringsFound = new Vector();
String remainingString = stringToSplit;
while(remainingString.length()>0){
int separatorStartingIndex = remainingString.indexOf(separator);
if(separatorStartingIndex==-1){
// Not separators found in the remaining String. Get substring and finish
stringsFound.addElement(remainingString);
break;
}
else{
// The separator is at the beginning of the String,
// Push the beginning at the end of separator and continue
if(remainingString.startsWith(separator)){
remainingString = remainingString.substring(separator.length());
}
// The separator is present and is not the beginning, add substring and continue
else{
stringsFound.addElement(remainingString.substring(0, separatorStartingIndex));
remainingString = remainingString.substring(separatorStartingIndex + separator.length());
}
}
}
return stringsFound;
}