Implode/explode a string: what escaping scheme would you suggest? - java

Suppose I have two strings to "join" with a delimiter.
String s1 = "aaa", s2 = "bbb"; // input strings
String s3 = s1 + "-" + s2; // join the strings with dash
I can use s3.split("-") to get s1 and s2. Now, what if s1 or s2 contains dashes? Suppose also that s1 and s2 may contain any ASCII printable and I don't want to use non-printable characters as a delimiter.
What kind of escaping would you suggest in this case?

If I could define the format, delimiters, etc. I would use OpenCSV and use it's defaults.

You could use an uncommon character sequence, such as ;:; as a delimiter instead of a single character.

Here is another working solution, that doesn't use a separator, but that joins the lengths of the strings at the end of the imploded string to be able to re-explode it after:
public static void main(String[] args) throws Exception {
String imploded = implode("me", "and", "mrs.", "jones");
System.out.println(imploded);
String[] exploded = explode(imploded);
System.out.println(Arrays.asList(exploded));
}
public static String implode(String... strings) {
StringBuilder concat = new StringBuilder();
StringBuilder lengths = new StringBuilder();
int i = 0;
for (String string : strings) {
concat.append(string);
if (i > 0) {
lengths.append("|");
}
lengths.append(string.length());
i++;
}
return concat.toString() + "#" + lengths.toString();
}
public static String[] explode(String string) {
int last = string.lastIndexOf("#");
String toExplode = string.substring(0, last);
String[] lengths = string.substring(last + 1).split("\\|");
String[] strings = new String[lengths.length];
int i = 0;
for (String length : lengths) {
int l = Integer.valueOf(length);
strings[i] = toExplode.substring(0, l);
toExplode = toExplode.substring(l);
i++;
}
return strings;
}
Prints:
meandmrs.jones#2|3|4|5
[me, and, mrs., jones]

Why don't you just store those strings in an array and join them with dash each time you want to display them to user?

Related

Merge 2 strings by printing the characters from each String one after the other

This is an interview which was asked recently.
Suppose there are 2 strings.
String a="test";
String b="lambda";
Reverse the String.
//tset
//adbmal
Expected output should be : tasdebtmal
Here we are trying to print characters from each string.
"t" from 1st String is printed, followed by "a" from other string, and so on.
So, "tasdebtm" is printed from each string and the remaining characters "al" is appended at the end.
int endA = a.length() - 1;
int endB = b.length() - 1;
StringBuilder str = new StringBuilder();
//add values to str till both the strings are not covered
while(endA>-1 && endB>-1){
str.append(a.charAt(endA--));
str.append(b.charAt(endB--));
}
add all chars of a if any is remaining
while(endA>-1){
str.append(a.charAt(endA--));
}
add all chars of b if any is remaining
while(endB>-1){
str.append(b.charAt(endB--));
}
System.out.println(str);
Definitely, there are other ways to do this too.
public class CharsinString2 {
public static void main(String[] args) {
String a="abra"; //arba
String b="kadabra";//arbadak // aarrbbaadak
int endA=a.length()-1;
int endB=b.length()-1;
StringBuilder str=new StringBuilder();
while(endA>-1 && endB>-1) {
str.append(a.charAt(endA--));
str.append(b.charAt(endB--));
}
while(endA>-1) {
str.append(a.charAt(endA--));
}
while(endB>-1) {
str.append(b.charAt(endB--));
}
System.out.println(str);
}
}

How to add spaces to left and right of chars in a string?

I'm trying to print out a string with spaces on either side of each char in the string
so if I have
String s = "abcde"
it would create something like this
a b c d e
with a space before the first char and three between each char.
I just haven't been able to find a way to do this with my knowledge.
Update
Updated requirement:
I failed to realize that I need something that add one place in front
of the first term and then 3 spaces between each term.
_0___0___0___0___0_ for example.
For the updated requirement, you can use yet another cool thing, String#join.
public class Main {
public static void main(String[] args) {
String s = "abcde";
String result = "_" + String.join("___", s.split("")) + "_";
System.out.println(result);
}
}
Output:
_a___b___c___d___e_
Original answer
There can be so many ways to do it. I find it easier to do it using Regex:
public class Main {
public static void main(String[] args) {
String s = "abcde";
String result = s.replaceAll(".", " $0 ");
System.out.println(result);
}
}
Output:
a b c d e
The Regex, . matches a single character and $0 replaces this match with space + match + space.
Another cool way is by using Stream API.
import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String s = "abcde";
String result = Arrays.stream(s.split(""))
.map(str -> " " + str + " ")
.collect(Collectors.joining());
System.out.println(result);
}
}
Output:
a b c d e
A super simple example, that doesn't handle a multitude of potential input scenarios.
public static void main(String[] args)
{
String s = "abcde";
for (int i = 0; i < s.length(); ++i) {
System.out.print("_" + s.charAt(i));
}
System.out.println("_");
}
NOTE: used an underscore rather than a space in order to allow visual check of the output.
Sample output:
_a_b_c_d_e_
Rather than direct output, one could use a StringBuilder and .append to a builder instead, for example.
Using StringBuilder:
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); ++i) {
sb.append('_').append(s.charAt(i));
}
sb.append('_');
System.out.println(sb.toString());
Based on a comment where the desired output is slightly different (two internal spaces, one leading and trailing space), this suggests an alternative approach:
public static String addSpace(String inp) {
StringBuilder sB = new StringBuilder();
String string = inp.trim();
String div = "___"; // spaces, or whatever
sB.append('_'); // add leading space
for(int index = 0; index < string.length(); ++index) {
sB.append(string.charAt(index))
.append(div); // two spaces
}
sB.setLength(sB.length() - (div.length() - 1) );
return (sB.toString());
}
NOTE: again using an underscore to allow for easier debugging.
Output when div is set to 3 underscores (or spaces):
_0___0___0___1___0___1___1___0_
You can define an empty string : result = “”;
Then go through the string you want to print with foreach loop With the function toCharArray()
(char character : str.toCharArray())
And inside this loop do ->
result += “ “ + character;
String result = s.chars().mapToObj(
Character::toString
).collect(Collectors.joining(" "));
Similar to the loop versions, but uses a Stream.
Another one liner to achieve this, by splitting the String into String[] of characters and joining them by space:
public class Main {
public static void main(String[] args) {
String s = "abcde";
System.out.println(" " + String.join(" ", s.split("")) + " ");
}
}
Output:
a b c d e
Edit:
The above code won't work for strings with Unicode codepoints like "👦ab😊", so instead of splitting on empty string, the split should be performed on regex: "(?<=.)".
public class Main {
public static void main(String[] args) {
String s = "abcde";
System.out.println(" " + String.join(" ", s.split("(?<=.)")) + " ");
}
}
Thanks to #saka1029 for pointing this out.
You can use Collectors.joining(delimiter,prefix,suffix) method with three parameters:
String s1 = "abcde";
String s2 = Arrays.stream(s1.split(""))
.collect(Collectors.joining("_+_", "-{", "}-"));
System.out.println(s2); // -{a_+_b_+_c_+_d_+_e}-
See also: How to get all possible combinations from two arrays?

Show common characters in two string without duplicates

I need to write a program that should ask two strings from user and show the common characters in this.
It must not have duplicates: even if ‘a’ is found more than once in both strings, it should be displayed only once.
My Java knowledge is very limited, so I'm not looking for efficiency but for understandability.
Here is what I came up with at the moment.
//Get String 1
System.out.print( "Enter a string: " );
string1 = sc.next();
//Get String 2
System.out.print( "Enter another string: " );
string2 = sc.next();
System.out.print ( "Common characters: " );
//Common chars
for ( a = 0 ; a < string1.length() ; a++){
for ( b = 0 ; b < string2.length() ; b++){
if ( string1.charAt(a) == string2.charAt(b) ){
System.out.print(string1.charAt(a));
}
Can anyone help me ?
You can use the chars() stream of the input string, e.g.:
public class StringCharCount {
public static void main(final String[] args) {
final String s1 = args[0];
final String s2 = args[1];
s1.chars()
.distinct()
.mapToObj(ch -> String.valueOf((char) ch))
.filter(s2::contains)
.forEach(System.out::println);
}
}
This works with Java 8 or later.
chars() creates a stream of characters from the string
distinct() ensures, that each value occurs only once
mapToObj(...) is required, because the String#contains() method requires a String as input. So we are converting the stream value to a String. Unfortunately, Java has issues with the primitive types, so the stream of chars is in fact a stream of int. So we have to cast each value to char.
forEach(...) prints each value to System.out
I would use a Set<Character>. This would naturally handle the duplicate issue and has a simple retainAll method to do the heavy lifting for you.
private Set<Character> characterSet(String s) {
Set<Character> set = new HashSet<>();
// Put each character in the string into the set.
for (int i = 0; i < s.length(); i++) {
set.add(s.charAt(i));
}
return set;
}
public Set<Character> common(String a, String b) {
// Make a set out of each string.
Set<Character> aSet = characterSet(a);
Set<Character> bSet = characterSet(b);
// Work out the common characters using retainAll.
Set<Character> common = new HashSet<>(aSet);
common.retainAll(bSet);
return common;
}
public void test(String[] args) throws Exception {
System.out.println(common("abcdef", "afxyzfffaa"));
}
You can use Set
String str1 = "abcdefg";
String str2 = "abcaaadefg";
StringBuilder result = new StringBuilder();
Set<Character> sets = new HashSet<Character>();
for(char ch : str1.toCharArray()){//init
sets.add(ch);
}
for(char ch : str2.toCharArray()){
if(sets.contains(ch)){//str1 char contains str2 char
result.append(ch);
sets.remove(ch);//avoid duplicates
}
}
System.out.println(result.toString());

A function that display the same text with two letters reversed

I'm trying to make an encryptor.What i want it to do:
Get the text i enter and reverse the first two letters of every word
and then display it again.
I have tried a lot of ways.This is the last one i've tried:
private void TranslateToEf(){
String storage = Display.getText();
String[] arr = storage.split("\\W+");
for ( String ss : arr) {
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String(c);
Display.appendText(swappedString + " ");
}
}
You may want to consider maintaining all the delimiters lost from the first String.split("\\W+") so they can be included in the final result. I would do that with a String.split("\\w+")
You may also want to consider that when you swap the first two letters, if the first letter is capital it becomes lowercase and the second letter becomes uppercase. Otherwise, just do a direct swap.
Code sample:
public static void main(String[] args) throws Exception {
String data = "Hello;World! My name is John. I write code.";
String[] words = data.split("\\W+");
String[] delimiters = data.split("\\w+");
int delimiterIndex = 0;
StringBuilder sb = new StringBuilder();
for (String word : words) {
if (word.length() < 2) {
sb.append(word);
} else {
char firstLetter = word.charAt(0);
char secondLetter = word.charAt(1);
if (Character.isUpperCase(firstLetter)) {
// Swap the first two letters and change casing
sb.append(Character.toUpperCase(secondLetter))
.append(Character.toLowerCase(firstLetter));
} else {
// Swap the first two letters
sb.append(secondLetter)
.append(firstLetter);
}
// Append the rest of the word past the first two letters
sb.append(word.substring(2));
}
// Append delimiters
if (delimiterIndex < delimiters.length) {
// Skip blank delimiters if there are any
while (delimiters[delimiterIndex].isEmpty()) {
delimiterIndex++;
}
// Append delimiter
sb.append(delimiters[delimiterIndex++]);
}
}
data = sb.toString();
// Display result
System.out.println(data);
}
Results:
Ehllo;Owrld! Ym anme si Ojhn. I rwite ocde.
public class Encrypto {
public static void main(String[] args) {
String input="Hello World";
String [] word = input.split(" ");
// System.out.println(word[0]);
String encryWord="";
for(int i=0;i<word.length;i++){
if (word[i].length() > 0) {
String tmp0 = String.valueOf(word[i].charAt(1));
String tmp1 = String.valueOf(word[i].charAt(0));
encryWord += tmp0.toLowerCase() + tmp1.toLowerCase() + word[i].substring(2) + " ";
}else{
encryWord +=word[i];
}
}
System.out.println(encryWord);
}
}
I think answer is more helpful for you
There are a few problems.
Declare zz outside the loop if you want to use it outside.
Append zz on every iteration. Not just assign it.
Something like this,
private void TranslateToEf(){
String storage = Display.getText();
String[] arr = storage.split("\\W+");
String zz = "";
for ( String ss : arr) {
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String(c);
String b= " ";
zz += swappedString + b;
}
Display.setText(zz + " ");
}
You are splitting with non-word (\W+) characters, but replacing it only with a space " ". This could alter the string with special characters.
Not sure what exactly you are looking for but i little modification in your code see if this suits your needs
String storage = "Test test t";
String[] arr = storage.split("\\W+");
String abc = "";
for ( String ss : arr) {
if(ss.length() > 1)
{
char c[] = ss.toCharArray();
char temp = c[0];
c[0] = c[1];
c[1] = temp;
String swappedString = new String( c );
String b = " ";
String zz = swappedString + b;
abc = abc + zz;
}else{
abc = abc + ss;
}
}
System.out.println(abc);
In Java strings are immutable. You can't modify them "on the fly", you need to reassign them to a new instance.
Additionally, you are setting the last display text to zz, but zz is a local variable to your loop, and therefore it gets re-instantiated with every iteration. In other words, you would be assigning to display only the last word!
Here is what you have to do to make it work:
String storage = Display.getText();
String[] arr = storage.split("\\W+");
String[] newText = new String[arr.length];
for ( int i = 0; i<arr.length; i++) {
String original = arr[i];
String modified = ((char) original.charAt(1)) + ((char) original.charAt(0)) + original.substring(2);
newText[i] = modified;
}
//Join with spaces
String modifiedText = Arrays.asList(newText).stream().collect(Collectors.join(" "));
Display.setText(modifiedText);
Note that:
1) We are assuming all strings have at least 2 chars
2) that your splitting logic is correct. Can you think some edge cases where your regexp fails?

How to increment a particular character in string (Java)

suppose i have a string s1 = "abcd";
output should be s1 = "abca";
I want to decrement/increment the last character in the string so that it matches the first character of the string .
Since String doesn't allow to modify the data
How can I achieve this.
Since, as you noted, String is immutable you will have to perform an assignment. I'd do a substring() and then concatenate the first letter. Something like
String s1 = "abcd";
s1 = s1.substring(0, s1.length() - 1) + s1.charAt(0);
System.out.println(s1);
Output is (as requested)
abca
JLS-4.2.1. Integral Types and Values does document that char is an integral type. That allows you to do something like
public static String modifyCharInString(String in, int index, int ammount) {
if (in == null || in.isEmpty() || index < 0 || index >= in.length()) {
return in;
}
StringBuilder sb = new StringBuilder(in);
sb.setCharAt(index, (char) (in.charAt(index) + ammount));
return sb.toString();
}
And then you an call it like
public static void main(String[] args) {
String s1 = "abcd";
s1 = modifyCharInString(s1, s1.length() - 1, -3);
System.out.println(s1);
}
Output is (again)
abca
For editing Strings you can use StringBuilder class. This allows you to get better performance, than using substring().
String oldString = "abcd";
StringBuilder sb = new StringBuilder(oldString);
sb.setCharAt(sb.length() - 1, sb.charAt(0));
String newString = sb.toString();

Categories