Is there a function in Java which is equivalent to php's strtr
?
string strtr ( string $str , string $from , string $to )
If given three arguments, strtr
function returns a copy of string where all occurrences of each (single-byte) character in $from
have been translated to the corresponding character in $to
, i.e., every occurrence of $from[$n]
has been replaced with $to[$n]
, where $n
is a valid offset in both arguments.
Cannot find a direct equivalence to your strtr
in the JDK. In Apache Commons StringUtils, there is StringUtils.replaceChars
String.replace Does not really fit your case, unless you use it for each letter in your $from
argument and replace it with the $to
substitute. It's pretty easy to implement your own utility function using StringBuilder and replacing it yourself, though. Which is pretty much what StringUtils.replace does.
You can call String.replace(char oldChar, char newChar)
in a cycle. For example:
String from = "abc";
String to = "xyz";
String str = "abc string";
for( int i = 0; i < from.length(); i++ )
str = str.replace(from.charAt(i), to.charAt(i));
Wrote the following two methods, since I was looking for something similar to the strtr functionality. Just copy and paste this code in your java project and use the two methods provided (Apache License 2.0):
Map<String, String> replacements = new TreeMap<String, String>();
replacements.put("this", "that");
replacements.put("that", "this");
replacements.put("Nothing much", "Everything");
String example = Strtr.replaceStringUsingMap("Whether this or that, whats the difference? Nothing much.", replacements);
System.out.println(example);
Input String:
"Whether this or that, whats the difference? Nothing much."
Output String:
"Whether that or this, whats the difference? Everything."
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* Two public methods can be used, mimicing strtr in php:
*
* {@link #replaceStringUsingChars(String, String, String)}
*
* {@link #replaceStringUsingMap(String, Map)}
* Apache 2.0 License
*
* @author Basil Musa
*/
public class Strtr {
/**
* Similar to strtr in php, characters in 'from' will be replaced by characters in 'to'
* in the same order character by character.
*
* @param haystack
* @param from
* @param to
* @return String having the replacements made
*/
public static String replaceStringUsingChars(String haystack, String from, String to) {
if (from.length() != to.length()) {
throw new IllegalArgumentException("from and to should have same number of characters.");
}
Map<String, String> replacements = new HashMap<String, String>();
int length = from.length();
for (int i = 0; i < length; i++) {
replacements.put(String.valueOf(from.charAt(i)), String.valueOf(to.charAt(i)));
}
return replaceStringUsingMap(haystack, replacements);
}
/**
* This method will return a string by replacing all occurrences of keys in needle2replacement occurring in
* haystack with the corresponding values. Once a replacement is made, it wont be replaced again.
*
* The method will start with the longest keys first.
* Keys of "" (empty strings) will be ignored.
*
* If the map is empty, the method returns the same haystack String directly.
*
* @param haystack The string to be replaced
* @param needle2replacement The map of keys to search and values to be replaced
* @return String containing haystack with all the replacements in needle2replacement made
*/
public static String replaceStringUsingMap(String haystack, Map<String, String> needle2replacement)
{
// To optimize, just return the haystack if the map has no items
if (needle2replacement.isEmpty()) {
return haystack;
}
// Sort map by length of keys please by longest string first
Map<String, String> sortedNeedle2replacement = sortKeysByLengthDescending(needle2replacement);
Set<String> arrNeedles = sortedNeedle2replacement.keySet();
List<Range> ranges = new ArrayList<>();
int lengthDifference = 0;
for (String needle : arrNeedles) {
int indexOf = -1;
// Ignore needles whom are empty strings
if (needle.equals("")) {
continue;
}
while(-1 != (indexOf = haystack.indexOf(needle, indexOf + 1))) {
String replacement = sortedNeedle2replacement.get(needle);
if (replacement == null) {
throw new IllegalArgumentException("Map value of null found in key ['" + needle + "']");
}
Range range = new Range(indexOf, indexOf + needle.length() - 1, needle, replacement);
// Check for any overlaps
boolean addRange = true;
for (Range target : ranges) {
if (range.isOverlappingWith(target)) {
addRange = false;
break;
}
}
if (addRange) {
ranges.add(range);
lengthDifference += range.replacement.length() - range.needle.length();
}
}
}
// Sort ranges please
Collections.sort(ranges, new Comparator<Range>() {
@Override
public int compare(Range o1, Range o2) {
return o1.begin - o2.begin;
}
});
// type them
StringBuilder stringBuilder = new StringBuilder(haystack.length() + lengthDifference);
int startAt = 0;
for (Range range : ranges) {
stringBuilder.append(haystack.substring(startAt, range.begin));
stringBuilder.append(range.replacement);
startAt = range.end + 1;
}
stringBuilder.append(haystack.substring(startAt));
return stringBuilder.toString();
}
private static class Range
{
public Range(int begin, int end, String needle, String replacement) {
super();
if (begin > end) {
throw new RuntimeException("begin [" + begin + "] should be smaller or equal to end [" + end + "]");
}
this.begin = begin;
this.end = end;
this.needle = needle;
this.replacement = replacement;
}
public final int begin;
public final int end;
public final String needle;
public final String replacement;
public String toString() {
return String.format("{%d,%d,%s,%s}", begin, end, needle, replacement);
}
/**
* @param target
* @return
*/
public boolean isOverlappingWith(Range target) {
final boolean liesBefore = this.end < target.begin;
final boolean liesAfter = this.begin > target.end;
if (liesBefore || liesAfter) {
return false;
}
return true;
}
/**
* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* XXXXXX
* YYYYYYYYYYYYYYYY
*
* Y is surround X as shown above
*
* @param target
* @return
*/
public boolean isSurrounding(Range target) {
if (this.begin < target.begin && this.end > target.end) {
return true;
}
return false;
}
}
private static Map<String, String> sortKeysByLengthDescending(
Map<String, String> needle2replacement) {
Map<String, String> sortedNeedle2replacement = new TreeMap<String, String>(new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
if (s1.length() > s2.length()) {
return -1;
} else if (s1.length() < s2.length()) {
return 1;
} else {
return s1.compareTo(s2);
}
}
});
sortedNeedle2replacement.putAll(needle2replacement);
return sortedNeedle2replacement;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With