replace char in string with "divider" - java

I'm trying to replace chars in a String.
Lets say the string is:
"yaaaaaaaay:axaxaxaxa:yaaaaaaay"
I want java to change all a after the : until the next : to X. So it will look like this:
"yaaaaaaaayXxXxXxXxXyaaaaaaay"
I tried the following and it did replace all a to X.
public static String replaceMiddle(String input, char divider) {
return input.replace( "a", "X");
}

public static void main(String[] args) {
String str ="yaaaaaaaay:axaxaxaxa:yaaaaaaay";
String[] strarr=str.split(":");
String str2=strarr[1].replace("a", "X");
String res=strarr[0]+str2+strarr[2];
System.out.println(res);
}

Could do something like this using Regex
public static String replaceMiddle(String input, char divider) {
String result = input;
Matcher matcher = Pattern.compile(":(\\w+):").matcher(input);
if(matcher.find()){
String mid = matcher.group(1).replace( "a", "X");
result = matcher.replaceAll(":" + mid + ":");
}
return result;
}
Not sure entirely on your use of divider but I think you intended to use it like so:
public static void main (String[] args) {
String input = "yaaaaaaaay:axaxaxaxa:yaaaaaaay";
System.out.println(replaceMiddle(input, ':'));
}
public static String replaceMiddle(String input, char divider) {
String result = input;
String regex = divider + "(\\w+)" + divider;
Matcher matcher = Pattern.compile(regex).matcher(input);
if(matcher.find()){
String mid = matcher.group(1).replace( "a", "X");
result = matcher.replaceAll(divider + mid + divider);
}
return result;
}

A short way to achieve that is by doing something like this:
String s = "yaaaaaaaay:axaxaxaxa:yaaaaaaay";
s = s.replace(s.substring(s.indexOf(":"), s.lastIndexOf(":")),
s.substring(s.indexOf(":"), s.lastIndexOf(":")).replace("a", "X"));
Output
yaaaaaaaay:XxXxXxXxX:yaaaaaaay

Related

Split String from the last iteration

This post is an update to this one : get specific character in a string with regex and remove unused zero
In the first place, i wanted to remove with an regular expression the unused zero in the last match.
I found that the regular expression is a bit overkill for what i need.
Here is what i would like now,
I would like to use split() method
to get from this :
String myString = "2020-LI50532-3329-00100"
this :
String data1 = "2020"
String data2 = "LI50532"
String data3 = "3329"
String data4 = "00100"
So then i can remove from the LAST data the unused Zero
to convert "00100" in "100"
And then concatenate all the data to get this
"2020-LI50532-3329-100"
Im not familiar with the split method, if anyone can enlight me about this ^^
You can use substring method to get rid of the leading zeros...
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + data[3]);
String result = sb.toString();
System.out.println(result);
Assuming that we want to remove the leading zeroes of ONLY the last block, maybe we can:
Extract the last block
Convert it to Integer and back to String to remove leading zeroes
Replace the last block with the String obtained in above step
Something like this:
public String removeLeadingZeroesFromLastBlock(String text) {
int indexOfLastDelimiter = text.lastIndexOf('-');
if (indexOfLastDelimiter >= 0) {
String lastBlock = text.substring(indexOfLastDelimiter + 1);
String lastBlockWithoutLeadingZeroes = String.valueOf(Integer.valueOf(lastBlock)); // will throw exception if last block is not an int
return text.substring(0, indexOfLastDelimiter + 1).concat(lastBlockWithoutLeadingZeroes);
}
return text;
}
Solution using regex:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
return str.replaceAll("0+(?=[1-9]\\d*$)", "");
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
Explanation of the regex:
One or more zeros followed by a non-zero digit which can be optionally followed by any digit(s) until the end of the string (specified by $).
Solution without using regex:
You can do it also by using Integer.parseInt which can parse a string like 00100 into 100.
public class Main {
public static void main(String[] args) {
// Test
System.out.println(parse("2020-LI50532-3329-00100"));
System.out.println(parse("2020-LI50532-3329-00001"));
System.out.println(parse("2020-LI50532-03329-00100"));
System.out.println(parse("2020-LI50532-03329-00001"));
}
static String parse(String str) {
String[] parts = str.split("-");
try {
parts[parts.length - 1] = String.valueOf(Integer.parseInt(parts[parts.length - 1]));
} catch (NumberFormatException e) {
// Do nothing
}
return String.join("-", parts);
}
}
Output:
2020-LI50532-3329-100
2020-LI50532-3329-1
2020-LI50532-03329-100
2020-LI50532-03329-1
you can convert the last string portion to integer type like below for removing unused zeros:
String myString = "2020-LI50532-3329-00100";
String[] data = myString.split("-");
data[3] = data[3].substring(2);
StringBuilder sb = new StringBuilder();
sb.append(data[0] + "-" + data[1] + "-" + data[2] + "-" + Integer.parseInt(data[3]));
String result = sb.toString();
System.out.println(result);
You should avoid String manipulation where possible and rely on existing types in the Java language. One such type is the Integer. It looks like your code consists of 4 parts - Year (Integer) - String - Integer - Integer.
So to properly validate it I would use the following code:
Scanner scan = new Scanner("2020-LI50532-3329-00100");
scan.useDelimiter("-");
Integer firstPart = scan.nextInt();
String secondPart = scan.next();
Integer thirdPart = scan.nextInt();
Integer fourthPart = scan.nextInt();
Or alternatively something like:
String str = "00100";
int num = Integer.parseInt(str);
System.out.println(num);
If you want to reconstruct your original value, you should probably use a NumberFormat to add the missing 0s.
The main points are:
Always try to reuse existing code and tools available in your language
Always try to use available types (LocalDate, Integer, Long)
Create your own types (classes) and use the expressiveness of the Object Oriented language
public class Test {
public static void main(String[] args) {
System.out.println(trimLeadingZeroesFromLastPart("2020-LI50532-03329-00100"));
}
private static String trimLeadingZeroesFromLastPart(String input) {
String delem = "-";
String result = "";
if (input != null && !input.isEmpty()) {
String[] data = input.split(delem);
StringBuilder tempStrBldr = new StringBuilder();
for (int idx = 0; idx < data.length; idx++) {
if (idx == data.length - 1) {
tempStrBldr.append(trimLeadingZeroes(data[idx]));
} else {
tempStrBldr.append(data[idx]);
}
tempStrBldr.append(delem);
}
result = tempStrBldr.substring(0, tempStrBldr.length() - 1);
}
return result;
}
private static String trimLeadingZeroes(String input) {
int idx;
for (idx = 0; idx < input.length() - 1; idx++) {
if (input.charAt(idx) != '0') {
break;
}
}
return input.substring(idx);
}
}
Output:
2020-LI50532-3329-100

Extract numbers from Strings, add them and convert back to string

I have couple of similar strings. I want to extract the numbers from them, add the numbers and convert it back to the same string format.
And the logic should be generic, i.e., it should work for any given strings.
Example:
String s1 = "1/9"; String s2 = "12/4"; The total of the above two Strings should be "13/13" (String again)
I know how to extract numbers from any given String. I referred: How to extract numbers from a string and get an array of ints?
But I don't know how to put them up back again to the same String format.
Can any one please help me over this?
Note: the string format can be anything, I have just taken an example for explanation.
Take a look at this:
public class StringTest {
public static void main(String[] args) {
String divider = "/";
String s1 = "1/9";
String s2 = "12/4";
String[] fragments1 = s1.split(divider);
String[] fragments2 = s2.split(divider);
int first = Integer.parseInt(fragments1[0]);
first += Integer.parseInt(fragments2[0]);
int second = Integer.parseInt(fragments1[1]);
second += Integer.parseInt(fragments2[1]);
String output = first + divider + second;
System.out.println(output);
}
}
The code prints:
13/13
Using a regex (and Markus' code)
public class StringTest {
public static void main(String[] args) {
String s1 = "1/9";
String s2 = "12&4";
String[] fragments1 = s1.split("[^\\d]");
String[] fragments2 = s2.split("[^\\d]");
int first = Integer.parseInt(fragments1[0]);
first += Integer.parseInt(fragments2[0]);
int second = Integer.parseInt(fragments1[1]);
second += Integer.parseInt(fragments2[1]);
String output = first + divider + second;
System.out.println(output);
}
}
You should be able to get from here to joining back from an array. If you're getting super fancy, you'll need to use regular expression capture groups and store the captured delimiters somewhere.
First, split your strings into matches and non-matches:
public static class Token {
public final String text;
public final boolean isMatch;
public Token(String text, boolean isMatch) {
this.text = text;
this.isMatch = isMatch;
}
#Override
public String toString() {
return text + ":" + isMatch;
}
}
public static List<Token> tokenize(String src, Pattern pattern) {
List<Token> tokens = new ArrayList<>();
Matcher matcher = pattern.matcher(src);
int last = 0;
while (matcher.find()) {
if (matcher.start() != last) {
tokens.add(new Token(src.substring(last, matcher.start()), false));
}
tokens.add(new Token(src.substring(matcher.start(), matcher.end()), true));
last = matcher.end();
}
if (last < src.length()) {
tokens.add(new Token(src.substring(last), false));
}
return tokens;
}
Once this is done, you can create lists you can iterate over and process.
For example, this code:
Pattern digits = Pattern.compile("\\d+");
System.out.println(tokenize("1/2", digits));
...outputs:
[1:true, /:false, 2:true]
Damn quick and dirty not relying on knowing which separator is used. You have to make sure, m1.group(2) and m2.group(2) are equal (which represents the separator).
public static void main(String[] args) {
String s1 = "1/9";
String s2 = "12/4";
Matcher m1 = Pattern.compile("(\\d+)(.*)(\\d+)").matcher(s1);
Matcher m2 = Pattern.compile("(\\d+)(.*)(\\d+)").matcher(s2);
m1.matches(); m2.matches();
int sum1 = parseInt(m1.group(1)) + parseInt(m2.group(1));
int sum2 = parseInt(m2.group(3)) + parseInt(m2.group(3));
System.out.printf("%s%s%s\n", sum1, m1.group(2), sum2);
}
Consider function:
public String format(int first, int second, String separator){
return first + separator + second;
}
then:
System.out.println(format(6, 13, "/")); // prints "6/13"
Thanks #remus. Reading your logic I was able to build the following code. This code solves the problem for any given strings having same format.
public class Test {
public static void main(String[] args) {
ArrayList<Integer> numberList1 = new ArrayList<Integer>();
ArrayList<Integer> numberList2 = new ArrayList<Integer>();
ArrayList<Integer> outputList = new ArrayList<Integer>();
String str1 = "abc 11:4 xyz 10:9";
String str2 = "abc 9:2 xyz 100:11";
String output = "";
// Extracting numbers from the two similar string
Pattern p1 = Pattern.compile("-?\\d+");
Matcher m = p1.matcher(str1);
while (m.find()) {
numberList1.add(Integer.valueOf(m.group()));
}
m = p1.matcher(str2);
while (m.find()) {
numberList2.add(Integer.valueOf(m.group()));
}
// Numbers extracted. Printing them
System.out.println("List1: " + numberList1);
System.out.println("List2: " + numberList2);
// Adding the respective indexed numbers from both the lists
for (int i = 0; i < numberList1.size(); i++) {
outputList.add(numberList1.get(i) + numberList2.get(i));
}
// Printing the summed list
System.out.println("Output List: " + outputList);
// Splitting string to segregate numbers from text and getting the format
String[] template = str1.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
// building the string back using the summed list and format
int counter = 0;
for (String tmp : template) {
if (Test.isInteger(tmp)) {
output += outputList.get(counter);
counter++;
} else {
output += tmp;
}
}
// Printing the output
System.out.println(output);
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch (NumberFormatException e) {
return false;
}
return true;
}
}
output:
List1: [11, 4, 10, 9]
List2: [9, 2, 100, 11]
Output List: [20, 6, 110, 20]
abc 20:6 xyz 110:20

Replace all occurences of certain char and get all variations

I have a word on which I need to replace a certain character with an asterisk, but I need to get all the replaced variations from this word. For eg. I want to replace character 'e' with an asterisk in:
String word = telephone;
but to get this list as a result:
List of words = [t*lephone, tel*phone, telephon*, t*l*phone, t*lephon*, tel*phon*, t*l*phon*];
Is there a quick way to do this in Java?
The following code will do that in a recursive way:
public static Set<String> getPermutations(final String string, final char c) {
final Set<String> permutations = new HashSet<>();
final int indexofChar = string.indexOf(c);
if (indexofChar <= 0) {
permutations.add(string);
} else {
final String firstPart = string.substring(0, indexofChar + 1);
final String firstPartReplaced = firstPart.replace(c, '*');
final String lastPart = string.substring(indexofChar + 1, string.length());
for (final String lastPartPerm : getPermutations(lastPart, c)) {
permutations.add(firstPart + lastPartPerm);
permutations.add(firstPartReplaced + lastPartPerm);
}
}
return permutations;
}
It adds the original String to the output, so:
public static void main(String[] args) {
String word = "telephone";
System.out.println(getPermutations(word, 'e'));
}
Outputs:
[telephone, t*lephone, tel*phone, t*l*phone, telephon*, t*lephon*, tel*phon*, t*l*phon*]
But you can always call remove on the returned Set with the original word.

Take (n) characters from a string

I have a string in java, of uncertain length, and I need to take the first 3 and last 3 characters and put them into new strings. Is there a simple way to do this?
Funny, all solutions are buggy (update: except the one with the regex) and may result in StringIndexOutOfBoundsException when the input string's length is less then 3 (the question explicitly says the length is uncertain). Assuming that str is not null, the proper way would be:
String first = str.substring(0, Math.min(str.length(), 3));
String second = str.substring(Math.max(0, str.length() - 3), str.length());
You could use the substring method:
String text = "Hello world!";
String newText = text.substring(0, 3) + text.substring(text.length-3);
This will take "Hello world!" and create a new string which is "Helld!".
If you are looking for a method that you can use:
String trimThreeCharacters(text){
return text.substring(0,3) + text.substring(text.length-3);
}
str.substring(0, 3) + str.substring(str.length - 3)
EDIT:
This code is not safe. I leave it for you to check whether string is not too short.
You can also use regular expressions:
Pattern p = Pattern.compile("^(.{3}).*(.{3})$");
Matcher m = p.matcher(str);
if (m.find()) {
String s1 = m.group(1);
String s2 = m.group(2);
}
Refer to documentation
public class Substring {
public static void main(String[] args) {
String input = "very long string, with random content";
System.out.println(input.substring(0, 3));
int length = input.length();
System.out.println(input.substring(length - 3));
}
}
Result
ver
ent
Another way of doing this
public class MyString
{
private String value;
public MyString(String p_value)
{
value = p_value;
}
public String getFirstThree()
{
return value.substring(0, 3);
}
public String getLastThree()
{
return value.substring(value.length() - 3);
}
public String getNewString()
{
return getFirstThree() + getLastThree();
}
public static void main(String[] args)
{
MyString example = new MyString("hello world");
String newString = example.getNewString();
System.out.println(newString);
}
}
new_string = old_string.substring(0,3) +
old_string.substring(old_string.lenght() - 3)
As milan already said, substring is the way to go here. You can see some examples of use here.
String FullName = "Cande Nauer";
String FirstNameChars = "";
FirstNameChars = FullName.substring( 0, 3 );
In this example, FirstNameChars will be "Can". To get the last three characters you will have to obtain the length og the string first.

How to flip two words in a string, Java

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();
}

Categories

Resources