Swapping Characters in a String in Java - java

Given the above excerpt from a Java code, I need to modify the code such that it could recursively swap pairs of the content of the string variable, "locationAddress".
Please note that the variable, "locationAddress", contains a string of characters, say, abcdefghij.
I wish to swap "abcdefghij" in pairs such that the result will be "badcfehgji".
Please kindly assist with the necessary modification to the above Java code excerpt to make it recursively swap pairs of characters in the string variable, "locationAddress".
public void format(DataObject dataSource) throws Exception {
String locationAddress = dataSource.getValueAsString("Location-Address").substring(4);
if (dataSource.parameterExists("Location-Address")) {
dataSource.setParameter("Parameter-Type","400");
dataSource.setParameter("Parameter-Value", locationAddress);
}
}

Here is a very simple way to do this using regex replacement in Java:
String input = "abcdefghij";
input = input.replaceAll("(.)(.)", "$2$1");
System.out.println(input);
badcfehgji
The idea is to walk down the string, starting at the beginning, capturing two characters at a time, in two different capture groups. Then, just swap those two captured characters in the replacement.

Here's one solution with StringBuilder:
public static String swapAdjacentPairs(String s) {
StringBuilder sb = new StringBuilder(s);
// divide 2 and then multiply by 2 to handle cases where the string length is odd
// we always want an even string length
// also note the i += 2
for (int i = 0 ; i < (s.length() / 2 * 2) ; i += 2) {
swapAdjacent(sb, i);
}
return sb.toString();
}
private static void swapAdjacent(StringBuilder sb, int index) {
char x = sb.charAt(index);
sb.setCharAt(index, sb.charAt(index + 1));
sb.setCharAt(index + 1, x);
}
Usage:
System.out.println(swapAdjacentPairs("abcdefghi"));

A solution using Stream:
String input = "abcdefghijk";
String swapped = IntStream.range(0, input.length())
.map(i -> i % 2 == 0 ? i == input.length() - 1 ? i : i + 1 : i - 1)
.mapToObj(input::charAt)
.map(String::valueOf)
.collect(Collectors.joining());
System.out.println(swapped); // badcfehgjik
The swapping is driven by the index i. If i is even and there is a next (i+1) character then it's used. If i is odd then the previous (i-1) character is used.

Related

Java: Split string by number of characters but with guarantee that string will be split only after whitespace

I want to achieve something like this.
String str = "This is just a sample string";
List<String> strChunks = splitString(str,8);
and strChunks should should be like:
"This is ","just a ","sample ","string."
Please note that string like "sample " have only 7 characters as with 8 characters it will be "sample s" which will break down my next word "string".
Also we can go with the assumption that a word will never be larger than second argument of method (which is 8 in example) because in my use case second argument is always static with value 32000.
The obvious approach that I can think of is looping thru the given string, breaking the string after 8 chars and than searching the next white space from the end. And then repeating same thing again for remaining string.
Is there any more elegant way to achieve the same. Is there any utility method already available in some standard third libraries like Guava, Apache Commons.
Splitting on "(?<=\\G.{7,}\\s)" produces the result that you need (demo).
\\G means the end of previous match; .{7,} means seven or more of any characters; \\s means a space character.
Not a standard method, but this might suit your needs
See it on http://ideone.com/2RFIZd
public static List<String> splitString(String str, int chunksize) {
char[] chars = str.toCharArray();
ArrayList<String> list = new ArrayList<String>();
StringBuilder builder = new StringBuilder();
int count = 0;
for(char character : chars) {
if(count < chunksize - 1) {
builder.append(character);
count++;
}
else {
if(character == ' ') {
builder.append(character);
list.add(builder.toString());
count = 0;
builder.setLength(0);
}
else {
builder.append(character);
count++;
}
}
}
list.add(builder.toString());
builder.setLength(0);
return list;
}
Please note, I used the human notation for string length, because that's what your sample reflects( 8 = postion 7 in string). that's why the chunksize - 1 is there.
This method takes 3 milliseconds on a text the size of http://catdir.loc.gov/catdir/enhancements/fy0711/2006051179-s.html
Splitting String using method 1.
String text="This is just a sample string";
List<String> strings = new ArrayList<String>();
int index = 0;
while (index < text.length()) {
strings.add(text.substring(index, Math.min(index + 8,text.length())));
index += 8;
}
for(String s : strings){
System.out.println("["+s+"]");
}
Splitting String using Method 2
String[] s=text.split("(?<=\\G.{"+8+"})");
for (int i = 0; i < s.length; i++) {
System.out.println("["+s[i]+"]");
}
This uses a hacked reduction to get it done without much code:
String str = "This is just a sample string";
List<String> parts = new ArrayList<>();
parts.add(Arrays.stream(str.split("(?<= )"))
.reduce((a, b) -> {
if (a.length() + b.length() <= 8)
return a + b;
parts.add(a);
return b;
}).get());
See demo using edge case input (that breaks some other answers!)
This splits after each space, then either joins up parts or adds to the list depending on the length of the pair.

How to insert a space in a charArray in an exact position [Java]

My problem is that I'm getting a String and I need to check if there is a space in the 4th position but starting from the end. If in this position there is not a space, I should insert it.
For example:
I get this String: TW12EF, need to get it like this: TW1 2EF
First of all I get the 4 last characters in a char array because I also need to check if they are numbers or letters.
With this method I check if there is a space:
public static boolean isSpace(){
return String.valueOf(charArray[0]).matches("[ \\t\\n\\x0B\\f\\r]");
}
charArray contains the last 4 characters of the input String
If charArray[0] wouldn't be a space, I want to insert a space in the 2nd place (charArray[1])
If there is something that I can correct in the question to make it easier to understand, just let me know and I will try to make it better for next questions.
A simple and direct solution (most likely faster than using a regular expression) is to get the 4th to the last character (if it exists), and if it isn't a white-space, insert a space at that position.
public static void main(String[] args) {
String str = "TW12EF";
int insertPos = str.length() - 4;
if (insertPos >= 0) {
char ch = str.charAt(insertPos);
if (!Character.isWhitespace(ch)) {
str = new StringBuilder(str).insert(insertPos + 1, ' ').toString();
}
}
System.out.println(str);
}
A whitespace is determined by invoking isWhitespace, which returns true for space but also tabs or line feeds, like you did in your question. The character is inserted by leveraging the StringBuilder#insert method, which is more direct that taking 2 substrings and concatenating them.
A quick, dirty regex will help :
String p = "TW12EF";
System.out.println(p.replaceAll("(.)\\s*(\\S.{2})$", "$1 $2")); // Select a character followed by 0 or more spaces and followed by 3 non-space characters. And replace multiple spaces if they exist with a single space
O/P :
TW1 2EF
Also works if there are one or more spaces after the 3rd char (from the left)
As char is a primitive data type, the comparison can be done simply with
if (charArray[0] == ' ') {
char[] temp = new char[5];
temp[0] = ' ';
for (int i = 1; i <= 4; i++) {
temp[i] = charArray[i - 1];
}
charArray = temp;
}
You could use something like:
public static void main(String[] args) {
String str = "TW12EF";
processStr(str);
}
public static final int SPACE_POS = 4, OFFSET = 1;
public static String processStr(String str)
{
if(!Character.isWhitespace(str.charAt(str.length() - SPACE_POS)))
{
str = String.format("%s %s", str.substring(0, str.length() - SPACE_POS + OFFSET), str.substring(SPACE_POS - OFFSET));
}
return str;
}
Like this?
` String s="TW12EF";
String result="";
int length=s.length();
for(int i=length-1;i>-1;i--){
if(i==length-4&&s.charAt(i)!=' '){
result+=" ";
}
result+=s.charAt(length-i-1);
}
System.out.println(result);`

Java string get latest 4 char reverse loop

I cannot figure how to obtain latest 4 char of string before zeroes
String str = "41f1f3d1f10000000000000000000000000000000000"
I want: d1f1
I've tried to revert string string than do straight loop
public static boolean checklast4digit(String risposta) {
String crc = "";
risposta = reverseIt(risposta);
for (int i = 0; i < risposta.length(); i++) {
if (risposta.charAt(i) != '0') crc = Character.toString(risposta.charAt(i + 3)) + Character.toString(risposta.charAt(i + 2)) + Character.toString(risposta.charAt(i + 1)) + Character.toString(risposta.charAt(i));
}
Log.i("Crc letto: ", crc);
return true;
}
public static String reverseIt(String source) { //Inversione stringa
int i, len = source.length();
StringBuilder dest = new StringBuilder(len);
for (i = (len - 1); i >= 0; i--) {
dest.append(source.charAt(i));
}
return dest.toString();
}
Exception:
java.lang.StringIndexOutOfBoundsException
As mentioned in the comments, you are looping too far. If you want to access charAt(i+3) you should only loop until i < risposta.length() - 3
Also, you need to break out of your loop, once you have found your result:
for(int i=0 ;i < risposta.length() - 3 ;i++){
if(risposta.charAt(i) != '0') {
crc= Character.toString(risposta.charAt(i + 3)) + Character.toString(risposta.charAt(i+2)) + Character.toString(risposta.charAt(i+1)) + Character.toString(risposta.charAt(i));
break;
}
}
Note that this only gives you a result, if you have 4 non-zero characters before the zeros.
There are many ways to improve your code, one of which would be to just remove the trailing zeroes first, then reverse the remaining string and take the first 4 chars of it.
However, to point out errors in your code...
Take a look at the values you're using to get characters. While your loop is limited to i<risposta.length(), i+3 that you're using in the line below is not - it can go up to risposta.length()+2. If oyu want to fix the code, then change the loop condition to i+3<risposta.length().
It's not elegant and can be done better, but that would solve the immediate bug in your code.
Your IndexOutOfBoundsException is caused by:
risposta.charAt(i + 3)
risposta.charAt(i+2)
risposta.charAt(i+1)
If you take a look at your for loop:
for(int i=0 ; i < risposta.length(); i++){
}
You are iterating from index 0 to risposta.length() - 1. However because you are getting the char at i+3 when i is risposta.length() - 1 it tries to access the index risposta.length() + 2 which is out of bounds.
You ned to modify your loop so you only iterate up to risposta.length() - 3
Here you have a oneliner!
String a = new StringBuilder(new StringBuilder("41f1f3d1f10000000000000000000000000000000000".split("0")[0]).reverse().toString().substring(0, 4)).reverse().toString();
And the complete code looks like this:
package nl.testing.startingpoint;
public class Main {
public static void main(String args[]) {
String a = new StringBuilder(new StringBuilder("41f1f3d1f10000000000000000000000000000000000".split("0")[0]).reverse().toString().substring(0, 4)).reverse().toString();
System.out.println(a);
}
}
result: d1f1
Alternatively, you could strip the 0's with a replaceAll and then get the last 4 chars with a substring. That makes the code pretty simple:
public static void main(String[] args) {
String str = "41f1f3d1f10000000000000000000000000000000000";
str = str.replaceAll("0*$", "");
System.out.println(str.substring(str.length()-4));
}
First of all the StringBuilder has a reverse method, which you can use to revers a string. That would simplify the reversing quite a bit.
return new StringBuilder(source).reverse().toString();
and as the others pointed out your for loop probably causes the exception, as it iterates to long.
To remove all trailing zeros (as suggested by CptBartender) you can use regex.
risposta = risposta.replaceFirst("0+$");
Then you can reverse the string (as shown above) and get the first n characters using the substring method.
reversed.substring(0, Math.min(reversed.length(), 4));
Math.min() is used to ensure there is no error if there are less than 4 characters before the zeros.

Finding variants of a string (only deletion, no transposition)

Given a string, I want to find all variants without transposition, only deletion. For example, given the string:
helloo
The list of variants would be as follows (separated by white space).
helloo hello heloo helo
My solution so far is to move through each character, and then if the current character matches the next character, recursively try the original and the deleted character version, as follows.
// takes String with at most two consecutive characters of any character,
// and returns an Iterable of all possible variants (e.g. hheello -> heello, hhello, ...)
private static Iterable<String> findAllVariants(String word) {
StringBuilder variant = new StringBuilder(word);
Queue<String> q = new LinkedList<String>();
findAllVariants(word, variant, 0, q);
return q;
}
// helper method
private static void findAllVariants(String word, StringBuilder variant, int currIndex, Queue<String> q) {
if (currIndex == variant.length() - 1) q.add(variant.toString());
for (int i = currIndex; i < variant.length() - 1; i++) {
char thisChar = variant.charAt(i);
char nextChar = variant.charAt(i+1);
if (thisChar == nextChar) {
// get all variants with repeat character
findAllVariants(word, variant, i+1, q);
// get all variants without repeat character;
variant = variant.deleteCharAt(i);
findAllVariants(word, variant, i, q);
}
}
}
However, I end up getting a large number of copies of answers, and none of others. When I do my algorithm on paper, it seems correct. What am I doing wrong?
Something along the lines of the following code will enable you to get all possibilities (remember to add word itself if needed). The idea is to retreive all possibilities for removing one char (e.g. hello results in ello hllo helo hell). These results can in turn be used to get the possibilities for removing two chars (remove one char again). Resulting in llo elo ell for ello and so on...
List<String> getPossibilities(String word) {
int removeChars = word.length() - 1;
List<String> possibilities = new ArrayList();
List<String> options = Arrays.asList(word);
for(int i = 0; i <= removeChars; i++) {
List<String> results = new ArrayList();
for(String option : options) {
for(String result : removeOneChar(option)) {
if(!results.contains(result)) {
results.add(result);
}
}
}
possibilities.addAll(results);
options = results;
}
return possibilities;
}
private static List<String> removeOneChar(String word) {
List<String> results = new ArrayList();
for(int i = 0; i < word.length(); i++) {
int secondPart = i + 2;
if(secondPart <= word.length()) {
results.add(
word.substring(0, i)
+ word.substring(i + 1, word.length()));
}
else {
results.add(
word.substring(0, i));
}
}
return results;
}
Notice the if(!contains(result)) in order to prevent any duplicates.
Note I've used substring() to accomplish this, you're approach with removeCharAt() is a another good option. You could run some tests to see which performs better to decide which one to use. Notice using the latter could possibly remove the need of the if in the private method.
I'd use rather different algorithm: I'd find all repetitions (ll) (oo) (lll) (ooo) etc.., keep an array describing their positions in the text, and the count of characters per each repetition.
e.g Array A =
[l|2]
[o|2]
.
.
.
Then I'd say have second array with initial count zero and increase there the count and print out all permutations:
Array B =
[l|1]
[o|1]
==> prints helo
Step 2: (increment count)
B =
[l|2]
[o|1]
==> prints hello
Step 3:
B =
[l|3] ==> bigger than max,so reset it to 0, and increment the second cell now, so it becomes:
B =
[l|1]
[o|2]
==> prints heloo
Step 4: (increment first elem again)
[l|2] ==> not bigger than max, so no overflow, so keeping it that way
[o|2]
==> prints helloo

How can I exchange the first and last characters of a string in Java?

I am practicing over the summer to try and get better and I am a little stuck on the following:
http://www.javabat.com/prob/p123384
Given a string, return a new string where the first and last chars have been exchanged.
Examples:
frontBack("code") → "eodc"
frontBack("a") → "a"
frontBack("ab") → "ba"
Code:
public String frontBack(String str)
{
String aString = "";
if (str.length() == 0){
return "";
}
char beginning = str.charAt(0);
char end = str.charAt(str.length() - 1);
str.replace(beginning, end);
str.replace(end, beginning);
return str;
}
Strings can be split into an array of chars and can be made with an array of chars. For more details on String objects, go to the Java API and click on String in the lower left pane. That pane is sorted alphabetically.
Edit: Since some people are being more thorough, I think I'll give additional details. Create a char array using String's .toCharArray() method. Take the first element and store it in a char, swap the first element with the last, and place the element you stored in a char into the last element into the array, then say:
String temp = new String(charArray);
and return that. This is assuming that charArray is your array of chars.
Rather than using the String.replace method, I'd suggest using the String.substring method to get the characters excluding the first and last letter, then concatenating the beginning and end characters.
Furthermore, the String.replace method will replace all occurrences of the specified character, and returns a new String with the said replacements. Since the return is not picked up in the code above, the String.replace calls really don't do much here.
This is because String in Java is immutable, therefore, the replace method cannot make any changes to the original String, which is the str variable in this case.
Also to add, this approach won't work well with Strings that have a length of 1. Using the approach above, a call to String.substring with the source String having a length of 1 will cause a StringIndexOutOfBoundsException, so that will also have to be taken care of as a special case, if the above approach is taken.
Frankly, the approach presented in indyK1ng's answer, where the char[] is obtained from the String and performing a simple swap of the beginning and end characters, then making a String from the modified char[] is starting to sound much more pleasant.
String instances in Java are immutable. This means that you cannot change the characters in a String; a different sequence of characters requires a new object. So, when you use the replace method, throw away the original string, and use the result of the method instead.
For this method, however, you probably want to convert the String instance to an array of characters (char[]), which are mutable. After swapping the desired characters, create a new String instance with that array.
A couple of hints:
Strings are immutable, meaning they cannot be changed. Hence, str.replace() does not change str, instead it returns a new string.
Maybe replace isn't the best... Consider frontBack("abcabc"): your function, if it were corrected, would replace 'a' with 'c' yielding "cbccbc", then 'c' with 'a' yielding "abaaba". That's not quite right!
The replace method in String actually returns a String, so if you were to insist on using replace, you'd do:
beginReplace = str.replace( beginning, end );
endReplace = beginReplace.replace( end, beginning );
return( str );
But this actually doesn't solve your specific problem, because replace replaces all occurences of a character in the string with its replacement.
For example, if my string was "apple" and I said "apple".replace( 'p', 'q' ), the resulting string would be "aqqle."
Yet another example without creating additional objects:
if (str.length() > 1) {
char[] chars = str.toCharArray();
// replace with swap()
char first = chars[0];
chars[0] = chars[chars.length - 1];
chars[chars.length - 1] = first;
str = new String(chars);
}
return str;
Edit: Performing the swap on length = 1 string is no-op.
Edit 2: dfa's change to copyValueOf did not make any sense as the Java source says in String.java: "// All public String constructors now copy the data." and the call is just delegated to a string constructor.
You could use a regex..
return str.replaceFirst("(.)(.*)(.)", "$3$2$1");
Just another, slightly different, approach, so you get a sense of the spectrum of possibilities. I commend your attention to the quick exit for short strings (instead of nesting the more-complicated processing in an if() clause), and to the use of String.format(), because it's a handy technique to have in your toolbox, not because it's notably better than regular "+" concatenation in this particular example.
public static String exchange(String s) {
int n = s.length();
if (n < 2)
return s;
return String.format("%s%s%s", s.charAt(n - 1), s.substring(1, n - 1), s.charAt(0));
}
Simple solution is:
public String frontBack(String str) {
if (str == null || str.length() == 0) {
return str;
}
char[] cs = str.toCharArray();
char first = cs[0];
cs[0] = cs[cs.length -1];
cs[cs.length -1] = first;
return new String(cs);
}
Using a character array (watch out for the nasty empty String or null String argument!)
Another solution uses StringBuilder (which is usually used to do String manupilation since String itself is immutable.
public String frontBack(String str) {
if (str == null || str.length() == 0) {
return str;
}
StringBuilder sb = new StringBuilder(str);
char first = sb.charAt(0);
sb.setCharAt(0, sb.charAt(sb.length()-1));
sb.setCharAt(sb.length()-1, first);
return sb.toString();
}
Yet another approach (more for instruction than actual use) is this one:
public String frontBack(String str) {
if (str == null || str.length() < 2) {
return str;
}
StringBuilder sb = new StringBuilder(str);
String sub = sb.substring(1, sb.length() -1);
return sb.reverse().replace(1, sb.length() -1, sub).toString();
}
Here the complete string is reversed and then the part that should not be reversed is replaced with the substring. ;)
if (s.length < 2) {
return s;
}
return s.subString(s.length - 1) + s.subString(1, s.length - 2) + s.subString(0, 1);
(untested, indexes may be of by one...
public String frontBack(String input)
{
return
input.substring(input.length() - 1) + // The last character
input.substring(1, input.length() - 1) + // plus the middle part
input.substring(0, 1); // plus the first character.
}
You can use a StringBuilder that represents "a mutable sequence of characters".
It has all methods needed to solve the problem: charAt, setCharAt, length and toString.
public String lastChars(String a, String b) {
if(a.length()>=1&&b.length()>=1){
String str = a.substring(0,1);
String str1 =b.substring(b.length()-1);
return str+str1;
}
else if(a.length()==0&&b.length()==0){
String v ="#";
String z ="#";
return v+z;
}
else if(a.length()==0&&b.length()>=1){
String s ="#";
String s1 = b.substring(b.length()-1);
return s+s1;
}
else if(a.length()>=1&&b.length()==0){
String f= a.substring(0,1);
String h = "#";
return f+h;
}
return a;
}
You can use this code:
public String frontBack(String str) {
if (str.length() <= 1)
return str;
String mid = str.substring(1, str.length()-1);
// last + mid + first
return str.charAt(str.length()-1) + mid + str.charAt(0);
}
class swap
{
public static void main(String[] args)
{
Scanner s=new Scanner(System.in);
System.out.println("no of elements in array");
int n=s.nextInt();
int a[]=new int[n];
System.out.println("Elements");
for(int i=0;i<n;i++)
{
a[i]=s.nextInt();
}
int b[]=new int[n];
for(int i=0;i<n;i++)
{
b[i]=a[i];
}
int end=n-1;
b[0]=b[end];
b[end]=a[0];
for(int i=0;i<n;i++)
{
System.out.println(b[i]);
}
}
}
if (str.length() <= 1) {
return str;
}
String mid = str.substring(1, str.length()-1);
return str.charAt(str.length()-1) + mid + str.charAt(0);
function frontBack(str: string) {
return str.slice(str.length - 1) + str.slice(1, -1) + str.slice(0, 1)
}
Slice will "cut out" the last letter. Counting the length of the string which is str.length -1, (plus) the reminder sliced string which starts at index 1 and is the last character which expressed at index -1, (plus) sliced last letter which is at index 0 through index 1.

Categories

Resources