I'm going to find number chars in a String and replace them with their Arabic versions.
The Code is:
public static void main(String[] args) {
String pattern = "[0-9]+";
Pattern p = Pattern.compile(pattern);
String mainText = "34titi685dytti5685fjjfj8585443";
Matcher m = p.matcher(mainText);
int i = 0;
while (m.find()) {
System.out.println("Match number " + i);
String tmp = m.group();
char[] cTmp = tmp.toCharArray();
for (int j = 0; j < cTmp.length; j++) {
cTmp[j] = (char) ((int) cTmp[j] + 1584);
}
m.group().replaceFirst(tmp,new String(cTmp));
i++;
}
System.out.println(mainText);
}
But at the end it prints the same string mainText.
What is wrong with my code?
This is not how you do a replacement using Matcher. m.group() just gives you the matched part of the string. Whatever replacement you do in it, you have to perform concatenation with original string. This is due to the fact that Strings are immutable objects. You don't perform in-place replacement to it.
The proper way to do this is to create a StringBuffer object, and use Matcher#appendReplacement and Matcher#appendTail methods.
You do it like this:
StringBuffer buffer = new StringBuffer();
while (m.find()) {
String tmp = m.group();
char[] cTmp = tmp.toCharArray();
for (int j = 0; j < cTmp.length; j++) {
cTmp[j] = (char) (cTmp[j] + 1584); // You don't need to typecast `cTmp[j]` to `int`.
}
m.appendReplacement(buffer, new String(cTmp));
}
m.appendTail(buffer);
System.out.println(buffer.toString());
String is final and immutable, you have to assign the new string to itself.
use StringBuilder to append the values every time.
StringBuilder stringBuilder = new StringBuilder();
//
//
m.group().replaceFirst(stringBuilder,new String(cTmp));
instead of
m.group().replaceFirst(tmp,new String(cTmp));
Assign the outcoming value to the mainText
Related
I have an input string, consisting of several lines, e.g.:
When I was younger
I never needed
And I was always OK
but it was a long Time Ago
The problem is to invert first letters of all the words which length is more than 3. That is an output must be the following:
when I Was Younger
I Never Needed
and I Was Always OK
But it Was a Long time ago
There is my code:
import java.util.regex.*;
public class Part3_1 {
public static void main(String[] args) {
String str = "When I was younger\r\nI never needed\r\nAnd I was always OK\r\nbut it was a long Time Ago";
System.out.println(convert(str));
}
public static String convert(String str) {
String result = "";
String[] strings = str.split(" ");
String regexLowerCase = "\\b[a-z]{3,}\\b";
String regexLowerCaseInitial = "(\\r\\n)[a-z]{3,}\\b";
String regexUpperCase = "\\b([A-Z][a-z]{2,})+\\b";
String regexUpperCaseInitial = "(\\r\\n)([A-Z][a-z]{2,})\\b";
Pattern patternLowerCase = Pattern.compile(regexLowerCase, Pattern.MULTILINE);
Pattern patternUpperCase = Pattern.compile(regexUpperCase, Pattern.MULTILINE);
Pattern patternLowerCaseInitial = Pattern.compile(regexLowerCaseInitial, Pattern.MULTILINE);
Pattern patternUpperCaseInitial = Pattern.compile(regexUpperCaseInitial, Pattern.MULTILINE);
for (int i = 0; i < strings.length; i++) {
Matcher matcherLowerCase = patternLowerCase.matcher(strings[i]);
Matcher matcherUpperCase = patternUpperCase.matcher(strings[i]);
Matcher matcherLowerCaseInitial = patternLowerCaseInitial.matcher(strings[i]);
Matcher matcherUpperCaseInitial = patternUpperCaseInitial.matcher(strings[i]);
char[] words = strings[i].toCharArray();
if (matcherLowerCase.find() || matcherLowerCaseInitial.find()) {
char temp = Character.toUpperCase(words[0]);
words[0] = temp;
result += new String(words);
} else if (matcherUpperCase.find() || matcherUpperCaseInitial.find()) {
char temp = Character.toLowerCase(words[0]);
words[0] = temp;
result += new String(words);
} else {
result += new String(words);
}
if (i < strings.length - 1) {
result += " ";
}
}
return result;
}
}
Here:
"\\b[a-z]{3,}\\b" is a regular expression, selecting all words in lower case which length is 3 or more symbols,
"\\b([A-Z][a-z]{2,})+\\b" is a regular expression, selecting all words starting from capital letter which length is 3 or more symbols.
Both regular expressions works properly but when we have a line breaks - they do not work. The output of my program execution is following:
when I Was Younger
I Never Needed
And I Was Always OK
but it Was a Long Time ago
As I understood, these regular expressions cannot select words And and but from needed\r\nAnd and OK\r\nbut respectively.
To fix this bug I tried to add new regular expressions "(\\r\\n)[a-z]{3,}\\b" and "(\\r\\n)([A-Z][a-z]{2,})\\b", but they do not work.
How to compose the regular expressions, selecting words after line breaks?
One option would be to split the string on a word break (\b) instead, and then pass the white space through to the final string in the strings array. This removes the need to have separate regex for the different situations, and also the need to add back space characters. This will give you the results you want:
public static String convert(String str) {
String result = "";
String[] strings = str.split("\\b");
String regexLowerCase = "^[a-z]{3,}";
String regexUpperCase = "^[A-Z][a-z]{2,}+";
Pattern patternLowerCase = Pattern.compile(regexLowerCase, Pattern.MULTILINE);
Pattern patternUpperCase = Pattern.compile(regexUpperCase, Pattern.MULTILINE);
for (int i = 0; i < strings.length; i++) {
Matcher matcherLowerCase = patternLowerCase.matcher(strings[i]);
Matcher matcherUpperCase = patternUpperCase.matcher(strings[i]);
char[] words = strings[i].toCharArray();
if (matcherLowerCase.find()) {
char temp = Character.toUpperCase(words[0]);
words[0] = temp;
result += new String(words);
} else if (matcherUpperCase.find()) {
char temp = Character.toLowerCase(words[0]);
words[0] = temp;
result += new String(words);
} else {
result += new String(words);
}
}
return result;
}
Output:
when I Was Younger
I Never Needed
and I Was Always OK
But it Was a Long time ago
Demo on rextester
I want to replace all the characters in a Java String with * character. So it shouldn't matter what character it is, it should be replaced with a *.
I know there are heaps of examples there on internet but have not one that replaces every character and I have tried myself but no success.
Java 11 and later
str = "*".repeat(str.length());
Note: This replaces newlines \n with *. If you want to preserve \n, see solution below.
Java 10 and earlier
str = str.replaceAll(".", "*");
This preserves newlines.
To replace newlines with * as well in Java 10 and earlier, you can use:
str = str.replaceAll("(?s).", "*");
The (?s) doesn't match anything but activates DOTALL mode which makes . also match \n.
Don't use regex at all, count the String length, and return the according number of stars.
Plain Java < 8 Version:
int len = str.length();
StringBuilder sb = new StringBuilder(len);
for(int i = =; i < len; i++){
sb.append('*');
}
return sb.toString();
Plain Java >= 8 Version:
int len = str.length();
return IntStream.range(0, n).mapToObj(i -> "*").collect(Collectors.joining());
Using Guava:
return Strings.repeat("*", str.length());
// OR
return CharMatcher.ANY.replaceFrom(str, '*');
Using Commons / Lang:
return StringUtils.repeat("*", str.length());
System.out.println("foobar".replaceAll(".", "*"));
public String allStar(String s) {
StringBuilder sb = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
sb.append('*');
}
return sb.toString();
}
How abt creating a new string with the number of * = number of last string char?
StringBuffer bf = new StringBuffer();
for (int i = 0; i < source.length(); i++ ) {
bf.append('*');
}
There may be other faster/better ways to do it, but you could just use a string buffer and a for-loop:
public String stringToAsterisk(String input) {
if (input == null) return "";
StringBuffer sb = new StringBuffer();
for (int x = 0; x < input.length(); x++) {
sb.append("*");
}
return sb.toString();
}
If your application is single threaded, you can use StringBuilder instead, but it's not thread safe.
I am not sure if this might be any faster:
public String stringToAsterisk(String input) {
if (input == null) return "";
int length = input.length();
char[] chars = new char[length];
while (length > 0) chars[--length] = "*";
return new String(chars);
}
Without any external library and without your own loop, you can do:
String input = "Hello";
char[] ca = new char[input.length()];
Arrays.fill(ca, '*');
String output = new String(ca);
BTW, both Arrays.fill() and String(char []) are really fast.
Recursive method
String nCopies(String s, int n) {
return n == 1 ? s.replaceFirst(".$", "") : nCopies(s + s, --n);
}
String text = "Hello World";
System.out.println( text.replaceAll( "[A-Za-z0-9]", "*" ) );
output : ***** *****
How can I extract only the numeric values from the input string?
For example, the input string may be like this:
String str="abc d 1234567890pqr 54897";
I want the numeric values only i.e, "1234567890" and "54897". All the alphabetic and special characters will be discarded.
You could use the .nextInt() method from the Scanner class:
Scans the next token of the input as an int.
Alternatively, you could also do something like so:
String str=" abc d 1234567890pqr 54897";
Pattern p = Pattern.compile("(\\d+)");
Matcher m = p.matcher(str);
while(m.find())
{
System.out.println(m.group(1));
}
String str=" abc d 1234567890pqr 54897";
Pattern pattern = Pattern.compile("\\w+([0-9]+)\\w+([0-9]+)");
Matcher matcher = pattern.matcher(str);
for(int i = 0 ; i < matcher.groupCount(); i++) {
matcher.find();
System.out.println(matcher.group());
}
Split your string into char array using yourString.toCharArray(); Then iterate through the characters and use Character.isDigit(ch); to identify if this is the numeric value. Or iterate through whole string and use str.charAt(i). For e.g:
public static void main(String[] args) {
String str = "abc d 1234567890pqr 54897";
StringBuilder myNumbers = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
if (Character.isDigit(str.charAt(i))) {
myNumbers.append(str.charAt(i));
System.out.println(str.charAt(i) + " is a digit.");
} else {
System.out.println(str.charAt(i) + " not a digit.");
}
}
System.out.println("Your numbers: " + myNumbers.toString());
}
You could do something like:
Matcher m = Pattern.compile("\\d+").matcher(str);
while (m.find()) {
System.out.println(m.group(0));
}
You can use str = str.replaceAll("replaced_string","replacing_string");
String str=" abc d 1234567890pqr 54897";
String str_rep1=" abc d ";
String str_rep2="pqr ";
String result1=str.replaceAll("", str_rep1);
String result2=str.replaceAll(",",str_rep2);
also what npinti suggests is fine to work with.
Example using java Scanner class
import java.util.Scanner;
Scanner s = new Scanner( "abc d 1234567890pqr 54897" );
s.useDelimiter( "\\D+" );
while ( s.hasNextInt() ){
s.nextInt(); // get int
}
If you do not want to use regex,
String str = " abc d 1234567890pqr 54897";
char[] chars = new char[str.length()];
int i = 0;
for (int j = 0; j < str.length(); j++) {
char c = str.charAt(j);
if (Character.isDigit(c)) {
chars[i++] = c;
if (j != chars.length - 1)
continue;
}
if (chars[0] == '\0')
continue;
String num = new String(chars).trim();
System.out.println(num);
chars = new char[str.length()];
i = 0;
}
Output :
1234567890
54897
String line = "This order was32354 placed 343434for 43411 QT ! OK?";
String regex = "[^\\d]+";
String[] str = line.split(regex);
String required = "";
for(String st: str){
System.out.println(st);
}
By above code you will get all the numeric values. then you can merge them or what ever you wanted to do with those numeric values.
You want to discard everything except digits and spaces:
String nums = input.replaceAll("[^0-9 ]", "").replaceAll(" +", " ").trim();
The extra calls clean up doubled and leading/trailing spaces.
If you need an array, add a split:
String[] nums = input.replaceAll("[^0-9 ]", "").trim().split(" +");
You could split the string on spaces to get the individual entries, loop across them, and try to parse them with the relevant method on Integer, using a try/catch approach to handle the cases where parsing it is as a number fails. That is probably the most straight-forward approach.
Alternatively, you can construct a regex to match only the numbers and use that to find them all. This is probably far more performant for a big string. The regex will look something like `\b\d+\b'.
UPDATE: Or, if this isn't homework or similar (I sort of assumed you were looking for clues to implementing it yourself, but that might not have been valid), you could use the solution that #npinti gives. That's probably the approach you should take in production code.
public static List<String> extractNumbers(String string) {
List<String> numbers = new LinkedList<String>();
char[] array = string.toCharArray();
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < array.length; i++) {
if (Character.isDigit(array[i])) {
stack.push(array[i]);
} else if (!stack.isEmpty()) {
String number = getStackContent(stack);
stack.clear();
numbers.add(number);
}
}
if(!stack.isEmpty()){
String number = getStackContent(stack);
numbers.add(number);
}
return numbers;
}
private static String getStackContent(Stack<Character> stack) {
StringBuilder sb = new StringBuilder();
Enumeration<Character> elements = stack.elements();
while (elements.hasMoreElements()) {
sb.append(elements.nextElement());
}
return sb.toString();
}
public static void main(String[] args) {
String str = " abc d 1234567890pqr 54897";
List<String> extractNumbers = extractNumbers(str);
for (String number : extractNumbers) {
System.out.println(number);
}
}
Just extract the digits
String str=" abc d 1234567890pqr 54897";
for(int i=0; i<str.length(); i++)
if( str.charAt(i) > 47 && str.charAt(i) < 58)
System.out.print(str.charAt(i));
Another version
String str=" abc d 1234567890pqr 54897";
boolean flag = false;
for(int i=0; i<str.length(); i++)
if( str.charAt(i) > 47 && str.charAt(i) < 58) {
System.out.print(str.charAt(i));
flag = true;
} else {
System.out.print( flag ? '\n' : "");
flag = false;
}
public class ExtractNum
{
public static void main(String args[])
{
String input = "abc d 1234567890pqr 54897";
String digits = input.replaceAll("[^0-9.]","");
System.out.println("\nGiven Number is :"+digits);
}
}
public static String convertBudgetStringToPriceInteger(String budget) {
if (!AndroidUtils.isEmpty(budget) && !"0".equalsIgnoreCase(budget)) {
double numbers = getNumericFromString(budget);
if( budget.contains("Crore") ){
numbers= numbers* 10000000;
}else if(budget.contains("Lac")){
numbers= numbers* 100000;
}
return removeTrailingZeroesFromDouble(numbers);
}else{
return "0";
}
}
Get numeric value from alphanumeric string
public static double getNumericFromString(String string){
try {
if(!AndroidUtils.isEmpty(string)){
String commaRemovedString = string.replaceAll(",","");
return Double.parseDouble(commaRemovedString.replaceAll("[A-z]+$", ""));
/*return Double.parseDouble(string.replaceAll("[^[0-9]+[.[0-9]]*]", "").trim());*/
}
}catch (NumberFormatException e){
e.printStackTrace();
}
return 0;
}
For eg . If i pass 1.5 lac or 15,0000 or 15 Crores then we can get numeric value from these fucntion . We can customize string according to our needs.
For eg. Result would be 150000 in case of 1.5 Lac
String str = "abc d 1234567890pqr 54897";
str = str.replaceAll("[^\\d ]", "");
The result will be "1234567890 54897".
String str = "abc34bfg 56tyu";
str = str.replaceAll("[^0-9]","");
output: 3456
So say I have a string called x that = "Hello world". I want to somehow make it so that it will flip those two words and instead display "world Hello". I am not very good with loops or arrays and obviously am a beginner. Could I accomplish this somehow by splitting my string? If so, how? If not, how could I do this? Help would be appreciated, thanks!
1) split string into String array on space.
String myArray[] = x.split(" ");
2) Create new string with words in reverse order from array.
String newString = myArray[1] + " " + myArray[0];
Bonus points for using a StringBuilder instead of concatenation.
String abc = "Hello world";
String cba = abc.replace( "Hello world", "world Hello" );
abc = "This is a longer string. Hello world. My String";
cba = abc.replace( "Hello world", "world Hello" );
If you want, you can explode your string as well:
String[] pieces = abc.split(" ");
for( int i=0; i<pieces.length-1; ++i )
if( pieces[i]=="Hello" && pieces[i+1]=="world" ) swap(pieces[i], pieces[i+1]);
There are many other ways you can do it too. Be careful for capitalization. You can use .toUpperCase() in your if statements and then make your matching conditionals uppercase, but leave the results with their original capitalization, etc.
Here's the solution:
import java.util.*;
public class ReverseWords {
public String reverseWords(String phrase) {
List<String> wordList = Arrays.asList(phrase.split("[ ]"));
Collections.reverse(wordList);
StringBuilder sbReverseString = new StringBuilder();
for(String word: wordList) {
sbReverseString.append(word + " ");
}
return sbReverseString.substring(0, sbReverseString.length() - 1);
}
}
The above solution was coded by me, for Google Code Jam and is also blogged here: Reverse Words - GCJ 2010
Just use this method, call it and pass the string that you want to split out
static String reverseWords(String str) {
// Specifying the pattern to be searched
Pattern pattern = Pattern.compile("\\s");
// splitting String str with a pattern
// (i.e )splitting the string whenever their
// is whitespace and store in temp array.
String[] temp = pattern.split(str);
String result = "";
// Iterate over the temp array and store
// the string in reverse order.
for (int i = 0; i < temp.length; i++) {
if (i == temp.length - 1) {
result = temp[i] + result;
} else {
result = " " + temp[i] + result;
}
}
return result;
}
Depending on your exact requirements, you may want to split on other forms of whitespace (tabs, multiple spaces, etc.):
static Pattern p = Pattern.compile("(\\S+)(\\s+)(\\S+)");
public String flipWords(String in)
{
Matcher m = p.matcher(in);
if (m.matches()) {
// reverse the groups we found
return m.group(3) + m.group(2) + m.group(1);
} else {
return in;
}
}
If you want to get more complex see the docs for Pattern http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html
Try something as follows:
String input = "how is this";
List<String> words = Arrays.asList(input.split(" "));
Collections.reverse(words);
String result = "";
for(String word : words) {
if(!result.isEmpty()) {
result += " ";
}
result += word;
}
System.out.println(result);
Output:
this is how
Too much?
private static final Pattern WORD = Pattern.compile("^(\\p{L}+)");
private static final Pattern NUMBER = Pattern.compile("^(\\p{N}+)");
private static final Pattern SPACE = Pattern.compile("^(\\p{Z}+)");
public static String reverseWords(final String text) {
final StringBuilder sb = new StringBuilder(text.length());
final Matcher wordMatcher = WORD.matcher(text);
final Matcher numberMatcher = NUMBER.matcher(text);
final Matcher spaceMatcher = SPACE.matcher(text);
int offset = 0;
while (offset < text.length()) {
wordMatcher.region(offset, text.length());
numberMatcher.region(offset, text.length());
spaceMatcher.region(offset, text.length());
if (wordMatcher.find()) {
final String word = wordMatcher.group();
sb.insert(0, reverseCamelCase(word));
offset = wordMatcher.end();
} else if (numberMatcher.find()) {
sb.insert(0, numberMatcher.group());
offset = numberMatcher.end();
} else if (spaceMatcher.find()) {
sb.insert(0, spaceMatcher.group(0));
offset = spaceMatcher.end();
} else {
sb.insert(0, text.charAt(offset++));
}
}
return sb.toString();
}
private static final Pattern CASE_REVERSAL = Pattern
.compile("(\\p{Lu})(\\p{Ll}*)(\\p{Ll})$");
private static String reverseCamelCase(final String word) {
final StringBuilder sb = new StringBuilder(word.length());
final Matcher caseReversalMatcher = CASE_REVERSAL.matcher(word);
int wordEndOffset = word.length();
while (wordEndOffset > 0 && caseReversalMatcher.find()) {
sb.insert(0, caseReversalMatcher.group(3).toUpperCase());
sb.insert(0, caseReversalMatcher.group(2));
sb.insert(0, caseReversalMatcher.group(1).toLowerCase());
wordEndOffset = caseReversalMatcher.start();
caseReversalMatcher.region(0, wordEndOffset);
}
sb.insert(0, word.substring(0, wordEndOffset));
return sb.toString();
}
What I'm referring to is concatenating Strings with a certain String in the middle, such as concatenating sentences separated by a period, or parameter lists with a comma. I know you can use libraries, but sometimes these can't do what you want, like when you want to generate the phrases you are concatenating. So far I've come up with two solutions,
StringBuffer sentence = new StringBuffer();
String period = "";
for ( int i = 0; i < sentences.length; i++ ) {
sentence.append( period + sentences[i] );
period = ". ";
}
which suffers from the redundant reassignment of period. There is also
StringBuffer actualParameters = new StringBuffer();
actualParameters.append( parameters[0] );
for ( int i = 1; i < parameters.length; i++ ) {
actualParameters.append( ", " + parameters[i] );
}
which removes the reassignment but which still looks unappealing. Any other solutions are greatly appreciated.
There is a family of functions in Apache Commons Lang that does just that.
If you have to code it yourself, the way I usually do this sort of thing is as follows:
StringBuilder sb = new StringBuilder();
for (String sentence : sentences) {
if (sb.length() != 0) {
sb.append(". ");
}
sb.append(sentence);
}
This version permits sentences to be any iterable (returning strings). Also note the use of StringBuilder instead of StringBuffer.
It is easy to generalize this to something akin to org.apache.commons.lang.StringUtils.join.
If you have at least one string then:
String join(String separator, String... strings)
{
String s = strings[0];
for (int i = 1; i < strings.length; i++) {
s += separator + strings[i];
}
return s;
}
Seems like a common question!
Remove last character of a StringBuilder?
That would lead to something like:
StringBuffer sentence = new StringBuffer();
String separator = ", ";
for ( int i = 0; i < sentences.length; i++ ) {
sentence.append( sentences[i] )
sentence.append( separator );
}
sentence.setLength(sentence.length() - separator.length());
public String join(String sep, String... parts) {
boolean first = true;
final StringBuilder sb = new StringBuilder();
for(String part: parts) {
if(first)
first = false;
else
sb.append(sep);
sb.append(part);
}
}
Don't use StringBuffer because of unnecessary synchronisation and "+" operator, because this will create unnecassry intemediate String objects.