3

So I was doing some standard programming interview questions and came across this one:

Reverse words in a string (words are separated by one or more spaces)

I thought it would be fun to do it using lambda expressions, but I found it difficult to get right and my solution feels kind of unwieldy and hacky. So now my question is: Is there a more idiomatic solution than mine?

public static String reverseWordsInString(String str)
{
    StringBuilder sb = new StringBuilder();

    Stream.of(str.split(" ")).forEach(
        word -> sb.append(reverseWord(word, !str.endsWith(word)))
    );
    return sb.toString();
}
public static String reverseWord(String str, boolean trailingSpace)
{
    StringBuilder sb = new StringBuilder();

    for(int i = str.length() - 1; i >= 0; i--)
    {
        sb.append(str.charAt(i));
    }
    sb.append(trailingSpace ? " " : "");
    return sb.toString();
}
user1870238
  • 447
  • 7
  • 20
  • http://stackoverflow.com/questions/24010109/java-8-stream-reverse-order (also, your split is wrong) – pvg Dec 09 '15 at 01:13

4 Answers4

3

Your task description is a bit ambiguous. I couldn’t recognize whether you have to reverse the words or reverse the characters of the words. But here are solutions for both:

public static String reverseWordsInString(String str) {
    return String.join(" ", Pattern.compile(" +").splitAsStream(str)
        .collect(LinkedList::new, LinkedList::addFirst, (a,b)->a.addAll(0, b)));
}

 

public static String reverseWordCharacters(String str) {
    return Pattern.compile(" +").splitAsStream(str)
        .map(word->new StringBuilder(word).reverse())
        .collect(Collectors.joining(" "));
}

The first one will reverse the words of a string, thus reverseWordsInString("this is an example") will return example an is this, the second one will reverse the characters of each word, so reverseWordCharacters("this is an example") yield siht si na elpmaxe.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Thanks, your last example was exactly what I was hoping for. Very insightful. :) – user1870238 Dec 09 '15 at 10:56
  • Can do without Pattern as well. – Arya Jun 05 '21 at 06:39
  • 1
    @AryA the pattern `" +"` reflects the task’s statement “*words are separated by one or more spaces*”. When you pass such a pattern to string’s `split` method, it will still use a `Pattern` behind the scenes. But using `splitAsStream` avoids creating an array containing all substrings. – Holger Jun 07 '21 at 06:57
2

Following pvg remark Java 8 stream reverse order answer this but it’s hard to figure it out from the question itself as it refers to ints.
So based on Venkata Raju answer in the above:

Arrays.stream(sentance.split("\\s+"))
         .collect(Collectors.toCollection(LinkedList::new))
         .descendingIterator().forEachRemaining(System.out::println);

Split and collect the result to an intermediate linked list and iterate on it in reverse order

Community
  • 1
  • 1
Haim Raman
  • 11,508
  • 6
  • 44
  • 70
0

The following should work in python where message is the message

def reverse_words(message):
    return ' '.join([x[::-1] for x in message[::-1].split(' ')])
0

Another solution without Pattern or regex. This is to reverse the words in the sentence, and not characters in the words.

public static String reverseWordsInString(String str) {
  return String.join(" ", Stream.of(str.split(" "))
                .collect(LinkedList::new, LinkedList::addFirst, (a,b)->a.addAll(0, b)));
}
Arya
  • 260
  • 1
  • 2
  • 13