Wolf Of Media
Wolf Of Media

Reputation: 15

Rearrange words in string in alphabetical order

I'm trying to rearrange words in any given string (20 words or less). I'm having this issue because I can not get the last word in the string to print. I tried modifying the loop range, but I am not able to fix the issue.

public class ListString {
    String[] list = new String[20];
    int n = 0;

    public void read() {
        Scanner in = new Scanner(System.in);
        System.out.println("Please enter the sentence");
        String s = in.nextLine();
        String temp = "";
        for (int i = 0; i < s.length(); i++)
        {
            char ch = s.charAt(i);
            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))  // range from a to z
                temp = temp + ch;
            else 
            {
                if (temp.length() > 0)
                {
                    list[n] = temp;
                    n++;
                    temp = "";
                }
            }
        }
    }

    public void print() {
        System.out.print(list[0]);          
        for (int i = 0; i < n; i++)
            System.out.print(" " + list[i]);          
        System.out.println(" ");
    }

    public void sort() {
        for (int i = 0; i < n; i++) { 
            String key = list[i]; 
            int j = i - 1; 
            while (j >= 0 && (list[j].compareToIgnoreCase(key) > 0)) 
            { 
                list[j + 1] = list[j]; 
                j = j - 1; 
            } 
            list[j + 1] = key; 
        } 
    }  
}

Upvotes: 1

Views: 804

Answers (2)

Andy Turner
Andy Turner

Reputation: 140319

You don't need to handle the end of the string explicitly: by using integer pointers to the start and end of words, you can do it as follows:

int start = 0;
while (start < s.length()) {
  // Increment a start pointer until it points to the end of the string or the start of a word.
  while (start < s.length() && !isLetter(s.charAt(start))) {
    start++;
  }

  // Increment an end pointer until it points to the end of the string or a non-word character.
  int end = start;
  while (end < s.length() && isLetter(s.charAt(end))) {
    end++;
  }

  if (start == end) {
    // You reached the end of the string.
    break;
  }

  // Grab the portion of the string between start and end, this is a word.
  list[n++] = s.substring(start, end);

  // Set up the start pointer to point to the end of this word, for the next iteration.
  start = end;
}

where isLetter(char) is a method that checks if the argument is between A and Z (in either case).

I have seen a variation on this method which avoids the inner while loops: I don't like this as much, as I think it's less clear to read; but it doesn't have quite so much repetitive checking of the length (I think this code works, not tried it):

for (int start = 0, end = 0; start < s.length();) {
  if (!isLetter(s.charAt(start))) {
    start++;
    end = start;
  } else if (isLetter(s.charAt(end))) {
    end++;

    if (end >= s.length() || !isLetter(s.charAt(end))) {
      list[n++] = s.substring(start, end);
      start = end;
    }
  }
}

Upvotes: 0

vszholobov
vszholobov

Reputation: 2363

That happens, when you hit end of the string and temp is not empty. To fix it you can add same if statement after loop:

for(int i = 0; i < s.length(); i++) {
    char ch = s.charAt(i);
    if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
        temp = temp + ch;
    } else {
        if(temp.length() > 0) {
            list[n] = temp;
            n++;
            temp = "";
        }
    }
}

if(temp.length() > 0) {
    list[n] = temp;
    n++;
    temp = "";
}

Also you would need to fix your output to not print first word twice:

public void print() {
    for(int i = 0; i < n; i++) {
        System.out.print(list[i] + " ");
    }
    System.out.println();
}

Output before fix:

a b c d e f g h i j k l m n o p q r s t
a a b c d e f g h i j k l m n o p q r s 

Output after fix:

a b c d e f g h i j k l m n o p q r s t
a b c d e f g h i j k l m n o p q r s t 

Update:

Also you can solve your problem in one line, using streams

public void read() {
    Scanner in = new Scanner(System.in);
    System.out.println("Please enter the sentence");
    String s = in.nextLine();

    String[] list = Arrays.stream(s.split(" ")).limit(20).sorted().toArray(String[]::new);
}

It splits input string by space character, takes first 20 words, sorts them and creates an array of them.

Output:

t s r q p o n m l k j i h g f e d c b a z z z z z
a b c d e f g h i j k l m n o p q r s t 

Upvotes: 2

Related Questions