I've got a very strange question. Say I am implementing an object that has a toString() method that returns a single string formatted in a square, as such:
010203
040506
070809
Now, clearly the entire string, when listed character-wise (and excluding the terminating \0), is as such:
010203\n040506\n070809\n
How would I go about concatenating entire square blocks like these? For instance, if I wanted to have:
010203 101112 010203101112
040506 + 131415 = 040506131415
070809 161718 070809161718
How could I do this? Note that I cannot import Java.util or any other classes.
Edit:
The example above was merely an example; ideally I'd like the solution to be extensible to an arbitrarily large number of 'square objects', where I could just call a hypothetical aSquareObject.squareConcat(otherSquareObject).squareConcat(anotherSquareObject).....squareConcat(finalSquareObject) method and it'd spit out two, three, five, fifteen squares side by side.
public class T27Concat {
public static void main(String[] args) {
String s1 = "010203\n040506\n070809";
String s2 = "101112\n131415\n161718";
String plus = " \n + \n ";
String equals = " \n = \n ";
System.out.println(concat(concat(concat(concat(s1, plus), s2), equals), concat(s1, s2)));
}
public static String concat(String s, String t) {
String[] ss = s.split("\n");
String[] tt = t.split("\n");
String result = "";
for (int i = 0; i < ss.length; i++) {
result += ss[i] + tt[i] + "\n";
}
return result.substring(0, result.length() - 1);
}
}
public class multiDarr {
public static void main(String[] args) {
String str1 = "010203\n040506\n070809\n";
String str2 = "010203\n040506\n070809\n";
String ttl = "";
for(int i = 0;i<str1.length();i= i+7){
ttl = ttl + str1.substring(i,i+6);
ttl = ttl +str2.substring(i,i+6);
ttl = ttl+'\n';
}
System.out.println(ttl);
//System.out.println(ttl);
}
}
you have to tune i = i+ n for your need , i put 7 because your original string have 6 chars,
result -
010203010203
040506040506
070809070809
I attempted solving this on paper, and arrived at a similar solution to that of #mayamar's:
public String sqConcat(String string1, String string2)
{
String[] rows1 = string1.split("\n");
String[] rows2 = string2.split("\n");
return new String(rows1[0] + rows2[0] + "\n"
+ rows1[1] + rows2[1] + "\n"
+ rows1[2] + rows2[2] + "\n");
}
Thanks for the help, everyone.
Related
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?
I have a string format like this which is output of
readAllBytes(new String(Files.readAllBytes(Paths.get(data))
from a file
a+2 b+3 c+33 d+88 ......
My scenario is I want to get the data after c+" ". The position of c is not constant but c occurs only once. It may occur anywhere. My required value will always be after c+ only. The required size of value 33.....is also not constant. Can someone help me with the optimal code please? I think collections need to be used here.
You can use this regex which will let you capture the data you want,
c\+(\d+)
Explanation:
c+ matches a literal c character immediately followed by a + char
(\d+) captures the next digit(s) which you are interested in capturing.
Demo, https://regex101.com/r/jfYUPG/1
Here is a java code for demonstrating same,
public static void main(String args[]) {
String s = "a+2 b+3 c+33 d+88 ";
Pattern p = Pattern.compile("c\\+(\\d+)");
Matcher m = p.matcher(s);
if (m.find()) {
System.out.println("Data: " + m.group(1));
} else {
System.out.println("Input data doesn't match the regex");
}
}
This gives following output,
Data: 33
This code is extracting the value right after c+ up to the next space, or to the end of the string if there is no space:
String str = "a+2 b+3 c+33 d+88 ";
String find = "c+";
int index = str.indexOf(" ", str.indexOf(find) + 2);
if (index == -1)
index = str.length();
String result = str.substring(str.indexOf(find) + 2, index);
System.out.println(result);
prints
33
or in a method:
public static String getValue(String str, String find) {
int index = str.indexOf(find) + 2;
int indexSpace = str.indexOf(" ", index);
if (indexSpace == -1)
indexSpace = str.length();
return str.substring(index, indexSpace);
}
public static void main(String[] args) {
String str = "a+2 b+3 c+33 d+88 ";
String find = "c+";
System.out.println(getValue(str, find));
}
I am trying to reverse a String word by word using recursion. (Ex: "Hello my friend" is reversed to "friend my Hello") This is the code I have attempted to write for this method. I have tried multiple similar variations but the output is only ever the first or last word of the String. I believe the part that is "broken" is the first if statement, but I am not quite sure.
public static String reverse (String words) {
Scanner sc = new Scanner(words);
String backwards = "";
if (sc.hasNext()) {
String currentWord = sc.next();
reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
} //end if
else {
backwards = words;
} //end else
return backwards;
}
I am aware that a few similar questions exist, but their answers have not seemed to help me understand my mistake(s).
Thanks!
Instead of using a Scanner, you can make use of an overload of String.split to split words around the first space:
public static String reverse(String words) {
String[] wordArr = words.split(" ", 2); // split into a maximum of 2 Strings
if (wordArr.length > 1) { // If there is more than 1 word
// return the first word (wordArr[0]),
// behind the reverse of the rest of the String (wordArr[1])
return reverse(wordArr[1]) + " " + wordArr[0];
}
return wordArr[0]; // else, just return the one word
}
You shouldn't call nextLine() because your input is all on one line. Your logic is much clearer if you begin by creating a simple helper method, it should take an array of words and a position; from there you can recursively build your desired output with something like
private static String reverse(String[] words, int p) {
if (p + 1 < words.length) {
return reverse(words, p + 1) + " " + words[p];
} else if (p < words.length) {
return words[p];
}
return "";
}
Then your public method is easy to implement, just split the original input on white space and call reverse starting at 0 (remembering to return the result). Like,
public static String reverse(String words) {
return reverse(words.split("\\s+"), 0);
}
And then, I tested it like
public static void main(String[] args) {
System.out.println(reverse("Hello my friend"));
}
Which outputs (as requested)
friend my Hello
Alternatively, you could make that helper take your Scanner instead like
private static String reverse(Scanner sc) {
if (sc.hasNext()) {
String currentWord = sc.next();
if (sc.hasNext()) {
return reverse(sc) + " " + currentWord;
}
return currentWord;
}
return "";
}
And then your public method is
public static String reverse(String words) {
return reverse(new Scanner(words));
}
public static String reverseSentence(String sentence) {
StringBuilder sb = new StringBuilder();
int firstSpace = sentence.indexOf(' ');
if (firstSpace == -1) {
return sb.append(sentence.strip()).append(" ").toString();
}
String secondPart = sentence.substring(firstSpace + 1);
String firstPart = sentence.substring(0, firstSpace);//similar to merger sort
return sb.append(reverseSentence(secondPart)).append(reverseSentence(firstPart)).toString();
}
You throw away the recursion results:
reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
Instead, use this:
backwards = reverse(sc.nextLine());
backwards = backwards + " " + currentWord;
Better yet:
backwards = reverse(sc.nextLine()) + " " + currentWord;
As stated in the comments, you could use a StringBuilder instead of Scanner class.
This example sends the same words, splits them by spaces each time you enter the method and you send the index of the word to be added in the next iteration.
For example:
public class RecursiveReverse {
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
String stringToReverse = "Hello my friend!";
System.out.println(reverse(stringToReverse, stringToReverse.split(" ").length - 1));
}
public static String reverse(String words, int i) {
if (i >= 0) { //If the index of the words is greater or equals the first word
sb.append(words.split(" ")[i]); //We split it and append it to our StringBuilder
sb.append(" "); //We append a space
reverse(words, --i); //We do this again
}
return sb.toString(); //When the above condition doesn't match we return the StringBuilder object as a String (which contains the words reversed)
}
}
Which produces this output:
friend! my Hello
A better method would be passing a String array as parameter so you split only once (when sending the words as an array to the method) the String.
public class RecursiveReverse {
static StringBuilder sb = new StringBuilder();
public static void main(String[] args) {
String stringToReverse = "Hello my friend!";
String words[] = stringToReverse.split(" ");
System.out.println(reverse(words, words.length - 1));
}
public static String reverse(String words[], int i) {
if (i >= 0) {
sb.append(words[i]);
sb.append(" ");
reverse(words, --i);
}
return sb.toString();
}
}
Do you must use recursion? You can do that without it.
public static String reverse(String words) {
String[] list = words.split(" ");
Collections.reverse(list);
String reversed = String.join(" ", list);
return reversed;
}
You must keep hold of the extracted words between calls in an accumulator. Here is an example.
public static String reverse(String words, String acc){
Scanner sc = new Scanner(words);
if(!sc.hasNext()){
return acc;
}
return reverse(sc.nextLine(), acc) + " " + sc.next();
}
You would call it like this.
reverse("Hello my friend", "");
It's not the most efficient implementation in the world, but yeah... It must work!
If you want a more efficient one, use a StringBuilder as the accumulator.
I have my string defined as
text1:text2:text3:text4:text5
I want to get output as
text1:text2:text3
using String methods.
I have tried using lastIndexOf, then substring and then again lastIndexOf.
I want to avoid these three steps with calling lastIndexOf two times.
Is there a better way to achieve this?
You can do this by running a loop to iterate over the characters of the string from index = 0 to index = lastIndexOf('3'). Here's the code:
String s = "text1:text2:text3:text4:text5";
for(int i = 0; i < = s.lastIndexOf('3'); i++)
System.out.print(s.charAt(i));
This gives you the required output.
OUTPUT:
text1:text2:text3
A regular expression could be used to identify the correct part of the string:
private static Pattern PATTERN = Pattern.compile("([^:]*:){2}[^:]*(?=:|$)");
public static String find(String input) {
Matcher m = PATTERN.matcher(input);
return m.find() ? m.group() : null;
}
Alternatively do not use substring between every call of lastIndexOf, but use the version of lastIndexOf that restricts the index range:
public static String find(String input, int colonCount) {
int lastIndex = input.length();
while (colonCount > 0) {
lastIndex = input.lastIndexOf(':', lastIndex-1);
colonCount--;
}
return lastIndex >= 0 ? input.substring(0, lastIndex) : null;
}
Note that here colonCount is the number of : that are left out of the string.
You could try:
String test = "text1:text2:text3:text4:text5";
String splitted = text.split(":")
String result = "";
for (int i = 0; i <3; i++) {
result += splitted[i] + ":"
}
result = result.substring(0, result.length() -1)
You can use the Java split()-method:
String string = "text1:text2:text3:text4:text5";
String[] text = string.split(":");
String text1 = text[0];
String text2 = text[1];
String text3 = text[2];
And then generate the output directly or with a for-loop:
// directly
System.out.println(text1 + ":" + text2 + ":" + text3);
// for-loop. Just enter, how many elements you want to display.
for(int i = 0; i < 3; i++){
System.out.println(text[i] + " ");
}
Output:
text1 text2 text3
The advantage of using this method is, that your input and output can be a bit more complex, because you have power over the order in which the words can be printed.
Example:
Consider Master Yoda.
He has a strange way of talking and often mixes up the sentence structure. When he introduces himself, he says the (incorrect!) senctence: "Master Yoda my name is".
Now, you want to create an universal translator, that - of course - fixes those mistakes while translating from one species to another.
You take in the input-string and "divide" it into its parts:
String string = "Master:Yoda:my:name:is"
String[] text = string.split(":");
String jediTitle = text[0];
String lastName = text[1];
String posessivePronoun = text[2];
String noun = text[3];
String linkingVerb = text[4];
The array "text" now contains the sentence in the order that you put it in. Now your translator can analyze the structure and correct it:
String correctSentenceStructure = posessivePronoun + " " + noun + " " + linkingVerb + " " + jediTitle + " " + lastName;
System.out.println(correctSentenceStructure);
Output:
"My name is Master Yoda"
A working translator might be another step towards piece in the galaxy.
Maby try this one-line s.substring(0, s.lastIndexOf('3')+1);
Complete example:
package testing.project;
public class Main {
public static void main(String[] args) {
String s = "text1:text2:text3:text4:text5";
System.out.println(s.substring(0, s.lastIndexOf('3')+1));
}
}
Output:
text1:text2:text3
I need to produce fixed length string to generate a character position based file. The missing characters must be filled with space character.
As an example, the field CITY has a fixed length of 15 characters. For the inputs "Chicago" and "Rio de Janeiro" the outputs are
" Chicago"
" Rio de Janeiro".
Since Java 1.5 we can use the method java.lang.String.format(String, Object...) and use printf like format.
The format string "%1$15s" do the job. Where 1$ indicates the argument index, s indicates that the argument is a String and 15 represents the minimal width of the String.
Putting it all together: "%1$15s".
For a general method we have:
public static String fixedLengthString(String string, int length) {
return String.format("%1$"+length+ "s", string);
}
Maybe someone can suggest another format string to fill the empty spaces with an specific character?
Utilize String.format's padding with spaces and replace them with the desired char.
String toPad = "Apple";
String padded = String.format("%8s", toPad).replace(' ', '0');
System.out.println(padded);
Prints 000Apple.
Update more performant version (since it does not rely on String.format), that has no problem with spaces (thx to Rafael Borja for the hint).
int width = 10;
char fill = '0';
String toPad = "New York";
String padded = new String(new char[width - toPad.length()]).replace('\0', fill) + toPad;
System.out.println(padded);
Prints 00New York.
But a check needs to be added to prevent the attempt of creating a char array with negative length.
This code will have exactly the given amount of characters; filled with spaces or truncated on the right side:
private String leftpad(String text, int length) {
return String.format("%" + length + "." + length + "s", text);
}
private String rightpad(String text, int length) {
return String.format("%-" + length + "." + length + "s", text);
}
For right pad you need String.format("%0$-15s", str)
i.e. - sign will "right" pad and no - sign will "left" pad
See my example:
import java.util.Scanner;
public class Solution {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("================================");
for(int i=0;i<3;i++)
{
String s1=sc.nextLine();
Scanner line = new Scanner( s1);
line=line.useDelimiter(" ");
String language = line.next();
int mark = line.nextInt();;
System.out.printf("%s%03d\n",String.format("%0$-15s", language),mark);
}
System.out.println("================================");
}
}
The input must be a string and a number
example input : Google 1
String.format("%15s",s) // pads left
String.format("%-15s",s) // pads right
Great summary here
import org.apache.commons.lang3.StringUtils;
String stringToPad = "10";
int maxPadLength = 10;
String paddingCharacter = " ";
StringUtils.leftPad(stringToPad, maxPadLength, paddingCharacter)
Way better than Guava imo. Never seen a single enterprise Java project that uses Guava but Apache String Utils is incredibly common.
You can also write a simple method like below
public static String padString(String str, int leng) {
for (int i = str.length(); i <= leng; i++)
str += " ";
return str;
}
The Guava Library has Strings.padStart that does exactly what you want, along with many other useful utilities.
Here's a neat trick:
// E.g pad("sss","00000000"); should deliver "00000sss".
public static String pad(String string, String pad) {
/*
* Add the pad to the left of string then take as many characters from the right
* that is the same length as the pad.
* This would normally mean starting my substring at
* pad.length() + string.length() - pad.length() but obviously the pad.length()'s
* cancel.
*
* 00000000sss
* ^ ----- Cut before this character - pos = 8 + 3 - 8 = 3
*/
return (pad + string).substring(string.length());
}
public static void main(String[] args) throws InterruptedException {
try {
System.out.println("Pad 'Hello' with ' ' produces: '"+pad("Hello"," ")+"'");
// Prints: Pad 'Hello' with ' ' produces: ' Hello'
} catch (Exception e) {
e.printStackTrace();
}
}
Here is the code with tests cases ;) :
#Test
public void testNullStringShouldReturnStringWithSpaces() throws Exception {
String fixedString = writeAtFixedLength(null, 5);
assertEquals(fixedString, " ");
}
#Test
public void testEmptyStringReturnStringWithSpaces() throws Exception {
String fixedString = writeAtFixedLength("", 5);
assertEquals(fixedString, " ");
}
#Test
public void testShortString_ReturnSameStringPlusSpaces() throws Exception {
String fixedString = writeAtFixedLength("aa", 5);
assertEquals(fixedString, "aa ");
}
#Test
public void testLongStringShouldBeCut() throws Exception {
String fixedString = writeAtFixedLength("aaaaaaaaaa", 5);
assertEquals(fixedString, "aaaaa");
}
private String writeAtFixedLength(String pString, int lenght) {
if (pString != null && !pString.isEmpty()){
return getStringAtFixedLength(pString, lenght);
}else{
return completeWithWhiteSpaces("", lenght);
}
}
private String getStringAtFixedLength(String pString, int lenght) {
if(lenght < pString.length()){
return pString.substring(0, lenght);
}else{
return completeWithWhiteSpaces(pString, lenght - pString.length());
}
}
private String completeWithWhiteSpaces(String pString, int lenght) {
for (int i=0; i<lenght; i++)
pString += " ";
return pString;
}
I like TDD ;)
Apache common lang3 dependency's StringUtils exists to solve Left/Right Padding
Apache.common.lang3 provides the StringUtils class where you can use the following method to left padding with your preferred character.
StringUtils.leftPad(final String str, final int size, final char padChar);
Here, This is a static method and the parameters
str - string needs to be pad (can be null)
size - the size to pad to
padChar the character to pad with
We have additional methods in that StringUtils class as well.
rightPad
repeat
different join methods
I just add the Gradle dependency here for your reference.
implementation 'org.apache.commons:commons-lang3:3.12.0'
https://mvnrepository.com/artifact/org.apache.commons/commons-lang3/3.12.0
Please see all the utils methods of this class.
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
GUAVA Library Dependency
This is from jricher answer. The Guava Library has Strings.padStart that does exactly what you want, along with many other useful utilities.
This code works great.
String ItemNameSpacing = new String(new char[10 - masterPojos.get(i).getName().length()]).replace('\0', ' ');
printData += masterPojos.get(i).getName()+ "" + ItemNameSpacing + ": " + masterPojos.get(i).getItemQty() +" "+ masterPojos.get(i).getItemMeasure() + "\n";
Happy Coding!!
public static String padString(String word, int length) {
String newWord = word;
for(int count = word.length(); count < length; count++) {
newWord = " " + newWord;
}
return newWord;
}
This simple function works for me:
public static String leftPad(String string, int length, String pad) {
return pad.repeat(length - string.length()) + string;
}
Invocation:
String s = leftPad(myString, 10, "0");
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 3; i++) {
int s;
String s1 = sc.next();
int x = sc.nextInt();
System.out.printf("%-15s%03d\n", s1, x);
// %-15s -->pads right,%15s-->pads left
}
}
}
Use printf() to simply format output without using any library.