Testing toString but it's failing? - java

Using this code:
public String toString()
{
StringBuilder s = new StringBuilder();
for (int i = 0; i < length; i++)
{
s.append(i).append(":").append(arr[i]).append(", ");
}
s.delete(s.length()-2, s.length()-1);
return s.toString();
}
is not passing this test:
#Test
public void testToString()
{
BetterArray<String> b = new BetterArray<String>();
assertEquals("", b.toString());
b.add("hello");
assertEquals("0:hello", b.toString());
b.add("bye");
assertEquals("0:hello, 1:bye", b.toString());
b.add("adios");
assertEquals("0:hello, 1:bye, 2:adios", b.toString());
}
It needs to start out as an empty string (""), am i doing that correctly? I'm new to StringBuilder. I'm using the s.delete to remove the trailing comma and space

This will cause a java.lang.StringIndexOutOfBoundsException in the case of empty string since you will not have comma and trailing space.
s.delete(s.length()-2, s.length()-1);

You're only deleting the comma, the delete line needs to be s.delete(s.length()-2, s.length());.
(By convention, the end index of a range points 1 past the last element of the range. This is the same for String.substring() for example.)

Here's one way to do what you want that doesn't rely on any math tricks. If the length is zero, the method returns an empty string.
public String toString() {
StringBuilder s = new StringBuilder();
for (int i = 0; i < length; i++) {
s.append(i);
s.append(":");
s.append(arr[i]);
if (i < (length - 1)) s.append(", ");
}
return s.toString();
}

Related

How do I break a string into groups of letters with a loop in Java?

I have to write a method which breaks a string into groups. The user should give the amount of letters per group and the function should return a string that consists of the input string broken into groups. For instance, function(“HELLOYOU”, 2) would return “HE LL OY OU”.
You can use String.split() to break the string into an array of individual letters, and then combine pairs of letters, or larger groups, etc.
Here is some example code:
String[] splitInParts(String input, int size) {
String[] letters = input.split("");
String[] output = new String[letters / size];
for (int i = 0; i < output.length; i++) {
output[i] = "";
for (int j = 0; j < size; j++) {
output[i] = output[i] + letters[size * i + j];
}
}
return output;
}
There is a lot of boilerplate code missing, for example, checking that loop parameters are in range, checking strings are not null, etc. However this is a rough idea of how you could go about doing it.
You can move the characters of input String to a new String and put whitespaces on every step that equals to "size":
String function(String input, int parts) {
StringBuilder result = new StringBuilder();
int partCounter = 0;
for (int i = 0; i < input.length(); i++) {
partCounter++;
result.append(input.charAt(i));
if (partCounter == parts){
result.append(" ");
partCounter = 0;
}
}
return result.toString();
}
You could use the below code that takes in a String instance and aN int defining the number of characters to split based on. And then use the String instances split method.
public static String[] split(String input, int len){
// To prevent any NullPointerException being thrown
if (StringUtils.isEmpty()) {
return null;
}
// Split the input string based on a regex pattern
return input.split(String.format("(?<=\\G.{%1$d})", len));
}
The Regular Expression that is being used here is (?<=\\G.{%1$d}) which based on len being 2 would become (?<=\\G.{2}). So this means it would split every 2 characters. So the output for a string of HELLOWORLD would be HE, LL, OW, OR, LD .
If you wanted to join those into one String separated by a space you could using the StringUtils#join method.
String joinedString = StringUtils.join(split, StringUtils.SPACE);
Which would produce "HE LL OW OR LD".
So an all in one method would be:
public static String separateNthCharacter(String input, int len) {
// To prevent any NullPointerException being thrown
if (StringUtils.isEmpty()) {
return StringUtils.EMPTY;
}
String[] split = input.split(String.format("(?<=\\G.{%1$d})", len));
return StringUtils.join(split, StringUtils.SPACE);
}

What's wrong with my code about swapping adjacent characters?

The question: Write a method called swapPairs that accepts a String as a parameter and returns that String with each pair of adjacent letters reversed. If the String has an odd number of letters, the last letter is unchanged. For example, the call swapPairs("example") should return "xemalpe" and the call swapPairs("hello there") should return "ehll ohtree".
public static String swapPairs(String s) {
String t="";
if(s.length()%2==0) {
for (int i=0;i<s.length()/2;i++) {
t+=s.charAt(2*i+1)+s.charAt(2*i);
}
}
else {
for (int i=0;i<s.length()/2;i++) {
t+=s.charAt(2*i+1)+s.charAt(2*i);
}
t+=s.charAt(s.length()-1);
}
return t;
}
You can use only 1 for cycles like:
public static String swapPairs(String s) {
StringBuilder t = new StringBuilder();
for(int i = 0; i < s.length() - 1; i += 2) {
t.append(s.charAt(i + 1));
t.append(s.charAt(i));
}
if(s.length() % 2 == 1) { //appending the last character if needed
t.append(s.charAt(s.length() - 1));
}
return t.toString();
}
Also using StringBuilder is a nice idea :)
String#charAt returns a char. Adding two chars will result in another char (because char is a numeric type), not in a String as you seem to expect. The compiler should give you an error message in that direction.
You could use String#substring instead.
You could just amend your method to use a StringBuilder instead and change it something like:
sb.append(s.charAt((2 * i) + 1)).append(s.charAt(2 * i));

merging multiple Strings in java

I have a task where I'm asked to create a method that merges multiple Strings so that the first character in the first string is followed by the first character in the 2nd String followed by the first character in the 3rd string and so on.
public static String merge(String... s)
if I would merge("AH", "HI", "U") the result would be AHUHI. I'm just not quite sure how to deal with this problem when the amount of Strings are unknown, someone has any idea how this could be executed?¨
This is what I tried:
public static String merge(String... s)
{
StringBuilder b = new StringBuilder();
for(int i = 0; i < s.length ; i++)
{
for(int y = 0; y < s.length ; y++)
{
b.append(s[y].charAt(i));
}
}
return b.toString();
}
and this is the exception I got:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
Find maxLength (the length of the longest String in your arguments) and change the outerloop to iterate maxLength times
Before you access a char of a String via charAt() check if the String is long enough, so you wont get the StringIndexOutOfBoundsException
Since you are already dealing with multiple input Strings, the code should work fine after these changes.
public static String merge(String... strings)
{
int maxLength = 0;
StringBuilder sb = new StringBuilder();
// find the longest
for (String s : strings)
if (s.length() > maxLength)
maxLength = s.length();
// build the output string
for (int i = 0; i < maxLength; i++)
for (String s : strings)
if (s.length() > i)
sb.append(s.charAt(i));
return sb.toString();
}
You're on the right lines, but you need to check that each string you're referencing is big enough not to throw the StringIndexOutOfBoundsException. So first, try getting the max string length:
public static String merge(String... s)
{
int maxLen = 0;
for (String str : s) // this loops through each string in the array s
{
maxLen = Math.max(maxLen, str.length());
}
// maxLen is now the length of the longest string;
StringBuilder b = new StringBuilder();
for (int i = 0; i < maxLen; ++i) // for each character position up to the max...
{
for (String str : s) // loop through each string:
{
if (str.length() > i) // check whether current string has any characters left
{
b.append(str.charAt(i));
}
}
}
return b.toString();
}
Thats how I would do it:
Basically, you loop though every String and always take the 1st, 2nd, 3rd, ... character of the String and append it to the StringBuilder.
private static String merge(String... strings) {
StringBuilder sb = new StringBuilder();
int adv;
boolean edited;
adv = 0;
edited = true;
while (edited) {
edited = false;
for (String s : strings) {
if (adv < s.length()) {
sb.append(s.charAt(adv));
edited = true;
}
}
adv++;
}
return sb.toString();
}
This is how I would do it:
public static String merge(String... s)
{
// Here we create a StringBuilder, this will store our result string
StringBuilder b = new StringBuilder();
// This boolean will control when we stop appending
boolean appended = true;
// The outer loop will loop over the indices of the available characters
// until we have no more characters to append
for (int i = 0; appended; ++i) {
// We have to default this to false to start our loop so that we don't
// exit early
appended = false;
// Loop over the individual strings that we were passed
for (String item : s) {
// If the string we are looking at has a character at the current
// position, we append it to our StringBuilder, otherwise we skip
// it
if (i < item.length()) {
b.append(item.charAt(i));
// Because we appeneded a character, we might have additional
// characters, so set this so that our loop continues
appended = true;
}
}
}
// Now we call the toString() method of StringBuilder to get a String
// result, which we return to our caller.
return b.toString();
}
Split each String into a array. Similar to this: Split string into array of character strings
Then go through the array and take out index 0 and assign it to a new string, and do that for index 1, and so on.

How can I append a word in between an array of strings?

I want to append the word AND between each string in an array, but I don't want it at the end of my string. Here is what I'm trying:
Assuming I want to pass First, Second, Third
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < myString.length -1;) {
sb.append("(" + myString[i] + " AND " + myString[i+1] + ")");
i++;
}
System.out.println(sb);
}
My output is (First AND Second)(Second AND Third)
But I want (First AND Second AND Third)
What am I doing wrong?
Append the "(" before your for loop so it prints only once. Similarly, append the ")" after your for loop so it prints only once. Finally, you can loop through your entire myString array, appending only that element, instead of two elements at a time, and only appending " AND " if needed.
Tweak your answer like this:
public void addString(String... myString) {
StringBuilder sb = new StringBuilder("(");
for(int i = 0; i < myString.length -1; i++) {
sb.append(myString[i] + " AND ");
}
if(myString.length == 0)
sb.append(")");
else
sb.append(myString[myString.length - 1]);
System.out.println(sb);
}
The only changes are:
Create the StringBuilder containing the starting (
Add all the elements except the last one, and append "AND" after it
Add the final element and the closing )
The repetitive part of your algorithm is the one that places the inner elements. This also covers the case where myString has length 1. In case of having no elements, the last addition is skipped and the closing ")" is added.
You should seperate the parts that you want just once from you for loop like this. So you want ( and ) once and there is only one word for wich you dont need AND in front of it.
public void addString(String[] myString)
{
StringBuilder sb = new StringBuilder();
sb.append("("+myString[0]);
for(int i = 1; i < myString.length;i++)
{
sb.append(" AND " + myString[i]);
}
sb.append(")")
System.out.println(sb);
}
To do what you want I'd probably use the join method in StringUtils.
StringUtils.join Docs
From the docs:
public static String join(Object[] array,
String separator)
Joins the elements of the provided array into a single String containing the provided list of elements.
No delimiter is added before or after the list. A null separator is the same as an empty String (""). Null objects or empty strings within the array are represented by empty strings.
StringUtils.join(null, *) = null
StringUtils.join([], *) = ""
StringUtils.join([null], *) = ""
StringUtils.join(["a", "b", "c"], "--") = "a--b--c"
StringUtils.join(["a", "b", "c"], null) = "abc"
StringUtils.join(["a", "b", "c"], "") = "abc"
StringUtils.join([null, "", "a"], ',') = ",,a"
Parameters:
array - the array of values to join together, may be null
separator - the separator character to use, null treated as ""
Returns:
the joined String, null if null array input
You can do the following -
Arrays.asList(myString).toString().replaceAll(",", " AND").replace("[", "(").replace("]", ")")
Arrays.asList(myString) converts the array to a List.
toString() converts it to a string which is like [ele1, ele2, ele
3].
Then using the replaceAll and replace method gives the
appropriate output.
The second option is to use the join method provided by StringUtils.
The approach used most often when you want separators between elements is to add the separator first, then the string. Only skipping the separator before the first element.
public void addString(String... myString) {
String separator = " AND ";
StringBuilder sb = new StringBuilder();
sb.append('(');
boolean needSeparator = false;
for(String string : myString) {
if (needSeparator) {
sb.append(separator);
} else {
needSeparator = true;
}
sb.append(string);
}
sb.append(')');
System.out.println(sb);
}
If you call addString("First", "Second", "Third") you'd get
(First AND Second AND Third)
This works perfectly fine with just 1 input addString("First")
(First)
Or even empty input addString() which would crash most other solutions I've seen here
()
It is possible to move printing the first element out of the loop so the loop does not have to check if it needs to omit the separator (minimal performance gain) but that results IMO in less readable code. E.g.:
if (myString.length > 0) {
// append first element without separator
sb.append(myString[0]);
// implicitly checks that length > 1
for (int i = 1; i < myString.length; i++) {
// append separator unconditionally
sb.append(separator);
sb.append(myString[i]);
}
}
Get the Apache CommonsLang package http://commons.apache.org/proper/commons-lang/
then use its StringUtils join() method as described here: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html
System.out.println(StringUtils.join(myString, ' AND '));
Append the parenthesis before and after the For Loop.
Append only one element in the String at a time.
Remove the final "AND " at the end of the String after the For Loop.
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
sb.append("(");
for(int i = 0; i < myString.length;) {
sb.append(myString[i] + " AND ");
i++;
}
sb = sb.substring(0, sb.length() - 5);
sb.append(")");
System.out.println(sb);
}
Try this:
public void addString(string[] myString) {
StringBuilder sb = new StringBuilder();
sb.Append("(");
for(int i = 0; i < myString.length; i++) {
sb.Append(myString[i] + " AND ");
}
string result = sb.ToString().Substring(0, sb.ToString().LastIndexOf("AND"));
result += ")";
System.out.println(result);
}
Corrected code:
public void addString(String... myString) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < myString.length; i++) {
if(i = 0){
sb.append("(" + myString[i])
}else if (i = myString.length-1){
sb.append(myString[i] + ")");
}else{
sb.append(myString[i])
}
sb.append("(" + myString[i] + " AND " + myString[i+1] + ")");
}
System.out.println(sb);
}
EDIT: Here is a better version based off of one of the answers above:
public void addString(String[] myString)
{
StringBuilder sb = new StringBuilder();
sb.append("(");
for(int i = 0; i < myString.length; i++){
sb.append(myString[i] + " AND ");
}
sb.append(")")
System.out.println(sb);
}

Java: how do icheck if a certain character is within a string, then print out the position it is in relative to the string?

What I am trying to do, is create a method, that has a string and a character as parameters, the method then takes the string and searches for the given character. If the string contains that character, it returns an array of integers of where the character showed up. Here is what I have so far:
public class Sheet {
public static void main(String[] args) {
String string = "bbnnbb";
String complete = null;
//*******
for(int i = 0; i < string.length(); i++){
complete = StringSearch(string,'n').toString();
}
//********
}
public static int[] StringSearch(String string, char lookfor) {
int[]num = new int[string.length()];
for(int i = 0; i < num.length; i++){
if(string.charAt(i)== lookfor){
num[i] = i;
}
}
return num;
}
}
The method works fine, and returns this:
0
0
2
3
0
0
What I am trying to do, is make those into 1 string so it would look like this "002300".
Is there any possible way of doing this? I have tried to do it in the starred area of the code, but I have had no success.
just do
StringBuffer strBuff = new StringBuffer();
for(int i = 0; i<str.length(); i++)
{
if(str.charAt(i) == reqChar)
{
strBuff.append(str.charAt(i));
}
else
{
strBuff.append('0');
}
}
return str.toString();
Just add the result to the existing string with the += operator
String complete = "";
for(...)
complete += StringSearch(string,'n').toString();
I would just use java's regex library, that way it's more flexible (eg if you want to look for more than just a single character). Plus it's highly optimized.
StringBuilder positions = "";
Pattern pattern = Pattern.compile(string);
Matcher matcher = pattern.matcher(lookfor);
while(matcher.find()){
positions.append(matcher.start());
}
return positions;
Updated with StringBuilder for better practices.
public static String StringSearch(String string, char lookfor) {
StringBuilder sb = new StringBuilder();
for(int i = 0; i < string.length; i++){
if(string.charAt(i) == lookfor)
sb.append(i);
else
sb.append("0");
}
return sb.toString();
}
Then you can just call it once, without a for loop. Not sure why you call it for every character in the string.
complete = StringSearch(string,'n');

Categories