can anyone please tell me how to write test case in the below code
public static String reverseWord(String str) {
String a[] = str.split(" ");
try {
for (int i = a.length - 1; i >= 0; i--) {
System.out.print(a[i] + " ");
}
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
I have written the below test case but it is failed
#Test
public void testReverseWord() {
assertEquals("world hello", Logic.reverseWord("hello world"));
}
You return exactly the same String as you get as argument, changes that you are doing are printed to the console instead of being returned.
Try this code instead. I am creating StringBuilder (you can read more about it here https://docs.oracle.com/javase/tutorial/java/data/buffers.html) which is used for String concatenation. Note that I am adding space only if it is not the last word - so that your returned String doesn't have space at the end. At the end by calling toString() on StringBuilder object I am returning new reversed String, exactly what you wanted.
public static String reverseWord(String str) {
String a[] = str.split(" ");
StringBuilder builder = new StringBuilder();
try {
for (int i = a.length - 1; i >= 0; i--) {
builder.append(a[i]);
if (i != 0) {
builder.append(" ");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return builder.toString();
}
Your test case is correct, but the method itself is wrong, you are splitting the string then just printing out values instead of creating a new string and concatenating those values there, so instead of System.out.print(a[i] + " "); introduce a new String outside the loop String result = "" and concatenate the values:
String a[] = str.split(" ");
String result = "";
for (int i = a.length - 1; i >= 0; i--) {
result += a[i];
if (i != 0)
result += " ";
}
return result;
A more optimized way is using a StringBuilder since a String is immutable every time you append to it, a new instance is created - also no need for a try-catch block
Your function return the same input, so you need to modify it, you can easily use StringBuilder class
public static String reverseWord(String str) {
String[] words = str.split(" ");
StringBuilder builder = new StringBuilder(str.length());
for (int i = words.length - 1; i >= 0; i--) {
builder.append(words[i]).append(" ");
}
return builder.toString().trim();
}
Related
I am currently implementing Run Length Encoding for text compression and my algorithm does return Strings of the following form:
Let's say we have a string as input
"AAAAABBBBCCCCCCCC"
then my algorithm returns
"1A2A3A4A5A1B2B3B4B1C2C3C4C5C6C7C8C"
Now I want to apply Java String split to solve this, because I want to get the highest number corresponding to character. For our example it would be
"5A4B8C"
My function can be seen below
public String getStrfinal(){
String result = "";
int counter = 1;
StringBuilder sb = new StringBuilder();
sb.append("");
for (int i=0;i<str.length()-1;i++) {
char c = str.charAt(i);
if (str.charAt(i)==str.charAt(i+1)) {
counter++;
sb.append(counter);
sb.append(c);
}
else {
counter = 1;
continue;
}
}
result = sb.toString();
return result;
}
public static String getStrfinal(){
StringBuilder sb = new StringBuilder();
char last = 0;
int count = 0;
for(int i = 0; i < str.length(); i++) {
if(i > 0 && last != str.charAt(i)) {
sb.append(count + "" + last);
last = 0;
count = 1;
}
else {
count++;
}
last = str.charAt(i);
}
sb.append(count + "" + last);
return sb.toString();
}
Here is one possible solution. It starts with the raw string and simply iterates thru the string.
public static void main(String[] args) {
String input = "AAAABBBCCCCCCCDDDEAAFBBCD";
int index = 0;
StringBuilder sb = new StringBuilder();
while (index < input.length()) {
int count = 0;
char c = input.charAt(index);
for (; index < input.length(); index++) {
if (c != input.charAt(index)) {
count++;
}
else {
break;
}
}
sb.append(Integer.toString(count));
sb.append(c);
count = 0;
}
System.out.println(sb.toString());
}
But one problem with this method and others is what happens if there are digits in the text? For example. What if the string is AAABB999222AAA which would compress to 3A2B39323A. That could also mean AAABB followed by 39 3's and 23 A's
Instead of string Buffer you can use a map it will be much easier and clean to do so.
public static void main(String[] args) {
String input = "AAAAABBBBCCCCCCCCAAABBBDDCCCC";
int counter=1;
for(int i=1; i<input.length(); i++) {
if(input.charAt(i-1)==input.charAt(i)) {
counter=counter+1;
}else if(input.charAt(i-1)!=input.charAt(i)){
System.out.print(counter+Character.toString(input.charAt(i-1)));
counter=1;
}if(i==input.length()-1){
System.out.print(counter+Character.toString(input.charAt(i)));
}
}
}
This will gives
5A4B8C3A3B2D4C
UPDATES
I Agree with #WJS if the string contains number the out put becomes messy
hence if the System.out in above code will be exchange with below i.e.
System.out.print(Character.toString(input.charAt(i-1))+"="+counter+" ");
then for input like
AAAAABBBBCCCCCCCCAAABBBDD556677CCCCz
we get out put as below
A=5 B=4 C=8 A=3 B=3 D=2 5=2 6=2 7=2 C=4 z=1
This is one of the possible solutions to your question. We can use a LinkedHashMap data structure which is similar to HashMap but it also maintains the order. So, we can traverse the string and store the occurrence of each character as Key-value pair into the map and retrieve easily with its maximum occurrence.
public String getStrFinal(String str){
if(str==null || str.length()==0) return str;
LinkedHashMap<Character,Integer> map = new LinkedHashMap<>();
StringBuilder sb=new StringBuilder(); // to store the final string
for(char ch:str.toCharArray()){
map.put(ch,map.getOrDefault(ch,0)+1); // put the count for each character
}
for(Map.Entry<Character,Integer> entry:map.entrySet()){ // iterate the map again and append each character's occurence into stringbuilder
sb.append(entry.getValue());
sb.append(entry.getKey());
}
System.out.println("String = " + sb.toString()); // here you go, we got the final string
return sb.toString();
}
So I'm supposed to write a method to print the elements of an array. This is how I did it:
public static void join(String phrase[])
{
for (int i = 0; i < phrase.length; i++)
{
System.out.print(phrase[i] + " ");
}
}
This code works, but the prof says we must return a String with this method, and I don't know how to do it this way. I tried:
public static String join(String phrase[])
{
for (int i = 0; i < phrase.length; i++)
{
String sentence = System.out.print(phrase[i] + " ");
return sentence;
}
}
Error: incompatible types: void cannot be converted to java.lang.String
I know I cannot use .print because the method is not void. But then, how do I print?
Any ideas? This is a beginner Java class, so I don't know any other way.
This would also work:
public static String join(String phrase[])
{
String sentence = "";
for (int i = 0; i < phrase.length; i++)
{
sentence += phrase[i] + " ";
}
return sentence;
}
Here is what I'm doing:
1) Creating an empty string outside the for loop that will be used to hold all the values of the array
2) Adding each element of array (with a space after) to the string with sentence += phrase[i] + " ";
3) Once the for loop adds all the elements to the string, return it!
System.out.println return void
You can't assign void to a String variable. You simply want to assign the concatenated value, not print it.
String sentence = phrase[i] + " "
You declare sentence each iteration
You need to concatenate each cells, so declare a variable before the loop and append the String in the loop
String sentence = "";
for (int i = 0; i < phrase.length; i++){
sentence += phrase[i] + " "; //same as sentence = sentence + phrase[i] + " ";
return sentence;
}
You return a value inside the loop...
The loop will end at the return, so only the first value will be present in the String. Only return the value after it is fully done, after the loop.
String sentence = "";
for (int i = 0; i < phrase.length; i++){
sentence += phrase[i] + " ";
}
return sentence;
FYI: In the same issues, if the array is empty, no value are returned, so it will also be a problem since a method should return a String in every cases (or throw an exception`.
Shorter solution :
This loop can be done simply with String.join since Java 8
return String.join(" ", phrase);
Please do the following:
public static String join(String phrase[]){
StringBuilder str = new StringBuilder();
for(String s: phrase){
str.append(s);
}
System.out.println(str);
return str.toString();
}
Dont use += and add the values of the string array to another string as it will create a new object every time you add a new string to the preprocessed string. Instead use StringBuilder which is more memory efficient.
You can also do the following:
public static String join(String phrase[]){
String str = Arrays.toString(phrase);
System.out.println(str);
return str;
}
This will print each elements and return the entire result :
public static String printElements(String phrase[]) {
String result = "";
for (int i = 0; i < phrase.length; i++)
{
System.out.print(phrase[i] + " ");
result += phrase[i];
if( i != phrase.length - 1)
{
result += " ";
}
}
return result;
}
I need to reverse 5 or more character long words in a given string. For example:
* Given string: My name is Michael.
* Output: My name is leahciM.
Rest of the sentence stays the same, just those long words get reversed.
So far I came up with this:
public static String spinWords(String sentence) {
String[] splitWords = sentence.split(" ");
String reversedSentence = "";
String reversedWord = "";
for (String str : splitWords) {
if (str.length() >= 5) {
for (int i = str.length() - 1; i >= 0; i--)
reversedWord += (str.charAt(i) + " ");
}
}
}
And I have reversed those words, but
1) they are in one string, without a space
2) I dont know how to put them back into their places in string
Here is a suggestion:
write a method that reverses a string:
private static String reverse(String s) { ... }
then in your main method, call it when necessary:
if (str.length() >= 5) str = reverse(str);
you then need to put the words back together, presumably into the reversedSentence string:
reversedSentence += str + " "; //you will have an extra space at the end
Side notes:
using a StringBuilder may prove more efficient than string concatenation for longer sentences.
you could put all the words back into a List<String> within the loop and call reversedSentence = String.join(" ", list) after the loop
reversing a string can be done in one line - you should find numerous related Q&As on stackoverflow.
You can use StringBuilder
public static String spinWords(String sentence) {
String[] splitWords = sentence.split(" ");
StringBuilder builder = new StringBuilder();
for (String str : splitWords) {
if (str.length() < 5) {
builder.append(str);
else
builder.append(new StringBuilder(str).reverse().toString());
builder.append(" ");
}
return builder.toString().trim();
}
No need to use anything else you almost had it, just check your "for" loops and remember to add the unreversed string.
public static String spinWords(String sentence) {
String[] splitWords = sentence.split(" ");
String reversedSentence = "";
String reversedWord;
for (String str : splitWords) {
if (str.length() >= 5) {
reversedWord = "";
for (int i = str.length() - 1; i >= 0; i--) {
reversedWord += (str.charAt(i));
}
reversedSentence += " " + reversedWord;
} else {
reversedSentence += " " + str;
}
}
return reversedSentence;
}
Use StringBuilder to build the answer as you process the elements in splitWords.
You may also find the idiom of space with special first-time value (being "") useful.
There was also a bug in your original code.
So here is what I would do:
public class ReverseLongWord {
public static void main(String[] args) {
String testInput = "My name is Michael";
System.out.println(spinWords(testInput));
}
public static String spinWords(String sentence) {
String[] splitWords = sentence.split(" ");
String reversedSentence = "";
StringBuilder sb = new StringBuilder();
String space = ""; // first time special
String reversedWord = "";
for (String str : splitWords) {
if (str.length() >= 5) {
for (int i = str.length() - 1; i >= 0; i--) {
reversedWord += (str.charAt(i)); // Bug fixed
}
sb.append(space + reversedWord);
} else {
sb.append(space + str);
}
space = " "; // second time and onwards
}
return sb.toString();
}
}
The output of this program is the following, as you have specified:
My name is leahciM
I think the reverse method as some people suggest would be the easiest way, here I share my implementation
public static void main(String[] args) {
System.out.println(concatenatePhrase("My name is Michael"));
System.out.println(concatenatePhrase("Some randoms words with differents sizes and random words"));
}
private static String concatenatePhrase(String phrase) {
StringBuilder completePhrase = new StringBuilder();
String[] phrases = phrase.split(" ");
for (String word : phrases) {
if (word.length() >= 5) {
completePhrase.append(reverseWord(word).append(" "));
} else {
completePhrase.append(word).append(" ");
}
}
return completePhrase.toString().trim();
}
private static StringBuilder reverseWord(String wordPassed) {
StringBuilder word = new StringBuilder(wordPassed);
return word.reverse();
}
I'm trying to do a simple reverse task like: change the string "how are you" to "you are how".
this is my code:
public class Program {
public static String revSentence (String str) {
String [] givenString = str.split(" ");
String [] retString = new String[givenString.length];
int last = givenString.length - 1;
for (int i = 0; i < givenString.length; i++) {
retString [i] = givenString[last--];
}
return retString.toString();
}
public static void main(String[] args) {
String m = "how are you";
System.out.println(revSentence(m));
}
}
I'm getting a weird output:
[Ljava.lang.String;#e76cbf7
The output isn't "weird" at all - it's the Object's internal string representation, created by Object.toString(). String[] doesnt override that. If you want to output all entires, loop through them and concatenate them, Best using a StringBuilder to avoid creating unnecessary String instances.
public static String arrayToString (String[] array) {
StringBuilder result = new StringBuilder();
for (String value : array) {
result.append(value);
}
return StringBuilder.toString();
}
If you don'T need that method on it'S own and want to include it in the overall process of reversing the sentence, this is how it may look. It iterates only once, iterating backwards (= counting down) to reverse the sentence.
public static String revSentence (String str) {
String [] givenString = str.split(" ");
StringBuilder result = new StringBuilder();
// no need for 'last', we can use i to count down as well...
for (int i = givenString.length - 1 ; i >= 0; i--) {
result.append(givenString[i]);
}
return result.toString();
}
[Edit]: because of the OPs comment to one of the other answers, about not having learned how to use StringBUilder yet, here is a arrayToStirng method without using one. Note however that this should not be done normally, as it creates useless instances of String whiche are not cleaned up by the GC because of the immutable nature of String(all instances are kept for reuse).
public static String arrayToString (String[] array) {
String result = "";
for (String value : array) {
result += value;
}
return result;
}
Or, without a dedicate arrayToString method:
public static String revSentence (String str) {
String [] givenString = str.split(" ");
String result = "";
for (int i = givenString.length-1 ; i >= 0 ; i--) {
result += givenString[i];
}
return result;
}
Here is a solution:
public class Program {
public static String revSentence (String str) {
String retString = "";
String [] givenString = str.split(" ");
for (int i=givenString.length-1; i>=0; i--) {
retString += givenString[i] + " ";
}
return retString;
}
public static void main(String[] args) {
String m = "how are you";
System.out.print(revSentence(m));
}
}
Modified it to make the "revSentence" function return a String, plus improved the code a bit. Enjoy!
Calling toString() on an array object (in your case retString) doesn't print all array entries, instead it prints object address.
You should print array entries by iterating over them.
Use this code for reversed string
StringBuilder builder = new StringBuilder();
for(String s : retString) {
builder.append(s);
}
return builder.toString();
Calling toString on an array gives you the memory ref which isn't very useful. Try this:
public static String revSentence (String str) {
String[] givenString = str.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = givenString.length - 1; i >= 0; i--) {
sb.append(givenString[i]);
if (i != 0)
sb.append(" ");
}
return sb.toString();
}
the for loop start from greater length to lower and builder.append(givenString[i] + " "); this will concatenate String and return whole sentence you are how you could use both mySentence += givenString[i] + " "; or builder.append(givenString[i] + " "); but the best way is to use StringBuilder class (see docs)
public class Program {
public static String revSentence(String str) {
String[] givenString = str.split(" ");
String[] retString = new String[givenString.length];
int last = givenString.length - 1;
//String mySentence = "";
StringBuilder builder = new StringBuilder();
for (int i = givenString.length - 1; i >= 0; i--) {
// retString [i] = givenString[i];
// mySentence += givenString[i] + " ";
builder.append(givenString[i] + " ");
}
return builder.toString(); // retuning String
//return mySentence;
}
public static void main(String[] args) {
String m = "how are you";
System.out.println(revSentence(m));
}
}
Faster, and shorter:
To reverse a word, use:
public String reverseWord(String s) {
StringBuilder y = new StringBuilder(s);
return y.reverse();
}
Now split and use this method and use Stringbuidler.append to concatenate the all.
And dont forget the space inbetween.
This is my first question in this forum...
I have a file with numerous data fields (both numeric and characters) in the file.
I want to delimit the file with set of delimiter length like 2,5,1,9,6 etc.
(Alternatively: I have a list of field lengths such as 2,5,1,9,6, and I want to insert comma delimiters in (a copy of) the source string after each field.)
For example, if my file is like this:
9483trdcvge245621jde
then I need to insert commas at 2,5,1,9,6 etc.
and the output will be:
94,83trd,c,vge245621,jde,
I need to do this in JAVA
Please help me to solve this issue.
Thanks in advance
if (myString.equals("9483trdcvge245621jde")) {
myString = "94,83trd,c,vge245621,jde";
}
Jokingly ;-)
I think something like this...
private static final int[] pos = {2, 5, 1, 9, 6};
private static final String DIV = ",";
public static String parse(String str) {
int start = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < pos.length; i++) {
if (i > 0) {
sb.append(DIV);
}
int end = start + pos[i];
if (end <= str.length()) {
sb.append(str.substring(start, end));
start = end;
} else {
sb.append(str.substring(start));
}
}
return sb.toString();
}
Read in the file as a StringBuilder then use something like this
StringBuilder sb = new StringBuilder(file); //The string builder
while (/*the string builder isn't finished*/)
{
int position = ;//The position you want the comma at 2 or 4 or whatever
sb.insert(position, ",");
}
Loop through as many times as needed.
I think i would do it this way
str being the input string
pos being the lengths of the parts after which we should put a comma
Code:
public static String partition(String str, int[] pos) {
int oldPos = 0;
StringBuilder builder = new StringBuilder(str.length() + pos.length);
for(int len : pos) {
builder.append(str.substring(oldPos, oldPos+len)).append(',');
oldPos += len;
}
builder.append(str.substring(oldPos)).append(',');
return builder.toString();
}
I think I don’t understand the question. Read the file, line by line, and insert commas into the string.
String newString = line.substring(0, firstComma) + "," + line.substring(firstComma + 1);
Of course this is terribly inefficient and can be optimized in numerous ways.
Assuming you have all these as Strings you can use String.substring(start, end). Then simply append + the substrings and commas together.
String data = "9483trdcvge245621jde";
String result = "";
result += data.substring(0,2) + ",";
result += data.substring(2, 7) + ",";
result += data.substring(7, 8) + ",";
etc...
Note: Using + to append string like this is very slow as it reallocates and moves data around each time. There are faster ways to concatenate Strings if speed is an issue.
String newString = "";
int[] positions = { 2, 5, 1, 9, 6 }; //etc
for (int i = 0; i > positions.length; i++) {
String tempString = "";
if (i == positions.length) { //for the last item
tempString = oldString.substring(0, positions[i]);
}
else { //every item except the last item
tempString = oldString.substring(0, positions[i]) + ",";
}
oldString = oldString.substring(positions[i]);
newString += tempString;
}
Stored the positions in an array. Iterate through, adding the delimited strings to a new string and removing them from the old one.
This might not be the best way, but its how I would do it. :P
Here's one solution:
package com.foo;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Commafy {
public static final String SEPARATOR = ",";
private static void fail(String message) {
System.err.println(message);
System.exit(1);
}
private static int[] argsAsInts(String[] args) {
if (args.length < 2) {
fail("argument list of file name followed by field lengths is required");
}
int[] result = new int[args.length - 1];
for (int i = 1; i < args.length; ++i) {
try {
result[i - 1] = Integer.parseInt(args[i]);
} catch (NumberFormatException nfe) {
fail("can't convert argument \"" + args[i] + "\" to integer");
}
}
return result;
}
private static int[] partialSums(int[] lengths) {
int[] result = new int[lengths.length];
int start = 0;
for (int i = 0; i < lengths.length; ++i) {
result[i] = start;
start += lengths[i];
}
return result;
}
private static int[] fieldsEndAt(int[] lengths, int[] starts) {
int[] result = new int[lengths.length];
for (int i = 0; i < lengths.length; ++i) {
result[i] = starts[i] + lengths[i];
}
return result;
}
private static void process(
String fileName, int[] starts, int[] ends
) throws IOException {
BufferedReader br = new BufferedReader(
new FileReader(fileName)
);
final int MIN_LENGTH = ends[ends.length - 1];
String line = br.readLine();
while (line != null) {
if (line.length() < MIN_LENGTH) {
System.err.println("short input line \"" + line +"\" skipped");
} else {
StringBuilder sb = new StringBuilder();
String separate = "";
for (int i = 0; i < starts.length; ++i) {
sb.append(separate).append(line.substring(starts[i], ends[i]));
separate = SEPARATOR;
}
System.out.println(sb.toString());
}
line = br.readLine();
}
br.close();
}
public static void main(String[] args) {
int[] lengths = argsAsInts(args);
int[] starts = partialSums(lengths);
int[] ends = fieldsEndAt(lengths, starts);
try {
process(args[0], starts, ends);
} catch (IOException e) {
fail("I/O Exception while processing input");
}
}
}
Given a data file named data/fixedlengthdata.text containing:
9483trdcvge245621jde
9483trdcvge245621jdelong
9483trdcvge245621
9483trdcvge245621jde
and run with arguments of:
data/fixedlengthdata.text 2 5 1 9 3
it produces output of:
94,83trd,c,vge245621,jde
94,83trd,c,vge245621,jde
short input line "9483trdcvge245621" skipped
94,83trd,c,vge245621,jde
(where the third line above goes to stderr, of course.)
This is probably the most bizzare requirement that I've ever seen, but anyway...
Psuedo-code
Collection<Integer> indexes; // initialized with indexes to add commas at
StringBuilder bldr = new StringBuilder();
for (int i = 0; i < inString.length(); i++){
bldr.append(inString.charAt(i));
if (indexes.contains(i))
bldr.append(",");
}
return bldr.toString();