7
\$\begingroup\$

Suppose I have an array of sentences:

[ "How To Format", "put returns between paragraphs", "for linebreak add 2 spaces at end" ]

I want to print it like this:

How put for
To returns linebreak
Format between add
 paragraphs 2
 spaces
 at
 end

Here's my code:

public static void solve(String[] sentences) {
 int n = sentences.length;
 if(n == 0)
 return;
 List<List<String>> matrix = new ArrayList<List<String>>();
 int maxLength = Integer.MIN_VALUE;
 for(String sentence : sentences) {
 List<String> words = Arrays.asList(sentence.split(" "));
 maxLength = Math.max(maxLength, words.size());
 matrix.add(words);
 }
 for(int col = 0; col < maxLength; col++) {
 for(int row = 0; row < matrix.size(); row++) {
 try {
 System.out.format("%-15s", matrix.get(row).get(col));
 }
 catch(IndexOutOfBoundsException e) {
 System.out.format("%-15s", "");
 }
 }
 System.out.println();
 }
}

Is this easy to understand? Can I make it simpler, such as by using different data structures?

asked Aug 21, 2015 at 6:30
\$\endgroup\$
13
  • \$\begingroup\$ I think that using try/catch for control flow isn't a very good idea. Simple if will suffice. \$\endgroup\$ Commented Aug 21, 2015 at 6:39
  • \$\begingroup\$ @justanothercoder In Java if is better, in Python try. \$\endgroup\$ Commented Aug 21, 2015 at 7:23
  • \$\begingroup\$ @Caridorc why is it better in Python? (In situation like this) \$\endgroup\$ Commented Aug 21, 2015 at 7:24
  • 1
    \$\begingroup\$ @justanothercoder A list is mostly filled, an ends only once. If you are going to succedd, try except is faster than if. More than performance though, it is idiomatic. \$\endgroup\$ Commented Aug 21, 2015 at 7:30
  • \$\begingroup\$ @Caridorc Okay, it seems persuasively. Thank you. \$\endgroup\$ Commented Aug 21, 2015 at 7:32

1 Answer 1

5
\$\begingroup\$

Use if statements rather than try/catch

Your method is understandable, you shouldn't use try catch, instead simply check that the index does not exceed the length. e.g.

if (col < matrix.get(row).size()) {
 // print what you want
} else {
 // print just a space
}

Better Regex

Rather than sentence.split(" "); The regex you want is sentence.split("\\s+) This ensures that you get all spaces and don't have an incorrect array length due to splitting on multiple empty spaces in a row. You can read more on Regex here.

Though this only applies if you don't want spaces to delimit words, ever, which is the assumption. The input itself sounds like it has to do with the specifications of the problem, but I simply took it as input and nothing more.

Use two dimensional arrays

You also don't need the list overhead for this. Simply use a two dimensional of the same size as the original array and make the inner arrays the result of calling the aforementioned split() method.

public static String[][] convertToWordArray(String[] input) {
 String[][] result = new String[input.length][];
 for (int i = 0; i < result.length; i++) {
 result[i] = input[i].trim().split("\\s+");
 }
 return result;
}

Alternative Implmentation:

public class Format {
 public static void main(String[] args) {
 String[] target = {
 "How To Format",
 "put returns between paragraphs",
 "for linebreak add 2 spaces at end"
 };
 printWordsVertically(target);
 }
/* These next two methods are relics of my initial implementation
 You can adjust for the use of 2d arrays and only need 1 method. */
 public static int wordCount(String input) {
 return input.trim().split("\\s+").length;
 }
 public static int longestWordCount(String[] input) {
 int result = 0;
 for (String s : input) {
 if (result < wordCount(s)) {
 result = wordCount(s);
 }
 }
 return result;
 }
 public static void printWordsVertically(String[] input) {
 int longestWordCount = longestWordCount(input);
 int spacesBetweenColumns = 7; // use needed int, or pass as argument
 String formatSpecifier = "%-" + (longestWordCount + spacesBetweenColumns) + "s";
 String[][] words = convertToWordArray(input);
 for (int i = 0; i < longestWordCount; i++) {
 for (int j = 0; j < words.length; j++) {
 if (i < words[j].length) {
 System.out.printf(formatSpecifier, words[j][i]);
 } else {
 System.out.printf(formatSpecifier, "");
 }
 }
 System.out.println();
 }
 }
 public static String[][] convertToWordArray(String[] input) {
 String[][] result = new String[input.length][];
 for (int i = 0; i < result.length; i++) {
 result[i] = input[i].trim().split("\\s+");
 }
 return result;
 }
}
answered Aug 21, 2015 at 12:43
\$\endgroup\$
2
  • \$\begingroup\$ thanks for the improvement. I've changed my list into a 2d array instead; I'll wait a little bit before I accept your answer \$\endgroup\$ Commented Aug 21, 2015 at 13:05
  • 2
    \$\begingroup\$ Yes, definitely do. You usually want to wait a couple of days. There could definitely be something even better! I'm glad this was helpful. \$\endgroup\$ Commented Aug 21, 2015 at 13:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.