简体   繁体   English

使用递归反转句子中的单词而不是标点符号

[英]Reverse the words in a sentence but not punctuation using recursion

How to reverse the words in a sentence, but not punctuation using recursion.如何使用递归来反转句子中的单词,而不是标点符号。 The sentence is said to use punctuation marks: ,.?!据说该句子使用标点符号:,.?!

Input: "Jack, come home!"输入:“杰克,回家!”

Output: "home, come Jack!" Output:“回家,杰克来了!”

Now I have somehow managed to complete the task correctly but without using recursion.现在我以某种方式设法正确完成了任务,但没有使用递归。 How should I convert this work to use recursion to solve the problem?我应该如何将这项工作转换为使用递归来解决问题?

Here's the method:这是方法:

public static StringBuilder reverseSentenceWithPunctuation(String sentence, int i) {
        String[] parts = sentence.split(" ");
        StringBuilder newSentence = new StringBuilder();
        Map<Integer, Character> punctuationMap = new HashMap<>();

        for (int j = 0; j < parts.length; j++) {
            if (parts[j].endsWith(",") || parts[j].endsWith(".") || parts[j].endsWith("!") || parts[j].endsWith("?")) {
                char lastSymbol = parts[j].charAt(parts[j].length()-1);
                punctuationMap.put(j, lastSymbol);
                String changedWord = parts[j].replace(String.valueOf(lastSymbol), "");
                parts[j] = changedWord;
            }
        }

        for (int j = parts.length-1; j >= 0; j--) {
            newSentence.append(parts[j]);
            if (punctuationMap.containsKey(i)) {
                newSentence.append(punctuationMap.get(i));
                newSentence.append(" ");
            } else
                newSentence.append(" ");
            i++;
        }
        return newSentence;
    }

Thanks in advance!提前致谢!

To implement this task using recursion, a pattern matching the first and the last words followed by some delimiters should be prepared:为了使用递归来实现这个任务,应该准备一个匹配第一个和最后一个单词的模式,然后是一些分隔符:

word1 del1 word2 del2 .... wordLast delLast

In case of matching the input the result is calculated as:在匹配输入的情况下,结果计算如下:

wordLast del1 REVERT(middle_part) + word1 delLast

Example implementation may be as follows (the words are considered to contain English letters and apostrophe ' for contractions):示例实现可能如下(单词被认为包含英文字母和撇号'用于缩写):

static Pattern SENTENCE = Pattern.compile("^([A-Za-z']+)([^A-Za-z]+)?(.*)([^'A-Za-z]+)([A-Za-z']+)([^'A-Za-z]+)?$");

public static String revertSentence(String sentence) {
    
    Matcher m = SENTENCE.matcher(sentence);
    if (m.matches()) {
        return m.group(5) + (m.group(2) == null ? "" : m.group(2)) 
            + revertSentence(m.group(3) + m.group(4)) // middle part
            + m.group(1) + (m.group(6) == null ? "" : m.group(6));
    }
    return sentence;
}

Tests:测试:

System.out.println(revertSentence("Jack, come home!"));
System.out.println(revertSentence("Jack, come home please!!"));
System.out.println(revertSentence("Jane cried: Will you come home Jack, please, don't go!"));

Output: Output:

home, come Jack!
please, home come Jack!!
go don't: please Jack home come you, Will, cried Jane!

I don't think this is a good case for a recursive function, mainly because you need 2 loops.我认为这不是递归 function 的好案例,主要是因为您需要 2 个循环。 Also, in general, iterative algorithms are better performance-wise and won't throw a stackoverflow exception.此外,一般来说,迭代算法在性能方面更好,并且不会引发 stackoverflow 异常。

So I think the main reasons to work with recursive functions is readability and easiness, and honestly, in this case, I think it isn't worth it.所以我认为使用递归函数的主要原因是可读性和易用性,老实说,在这种情况下,我认为它不值得。

In any case, this is my attempt to convert your code to a recursive function.无论如何,这是我将您的代码转换为递归 function 的尝试。 As stated before, I use 2 functions because of the 2 loops.如前所述,由于有 2 个循环,我使用了 2 个函数。 I'm sure there is a way to achieve this with a single function that first loads the map of punctuations and then compose the final String, but to be honest that would be quite ugly.我确信有一种方法可以使用单个 function 来实现这一点,它首先加载 map 的标点符号,然后组成最终的字符串,但老实说这会很丑陋。

import java.util.*;
import java.util.stream.*;

public class HelloWorld{

    static Character[] punctuationCharacters = {',','.','!'};

    public static void main(String []args){
        System.out.println(reverseSentenceWithPunctuation("Jack, come home!"));
    }
     
    private static String reverseSentenceWithPunctuation(String sentence) {
        
        String[] parts = sentence.split(" ");

        return generate(0, parts, extractPunctuationMap(0, parts));
    }
     
    private static Map<Integer, Character> extractPunctuationMap(int index, String[] parts){
        Map<Integer, Character> map = new HashMap<>();
        if (index >= parts.length) {
            return map;
        }
        char lastSymbol = parts[index].charAt(parts[index].length() - 1);
        if (Arrays.stream(punctuationCharacters).anyMatch(character -> character == lastSymbol)) {
            parts[index] = parts[index].substring(0, parts[index].length() - 1);
            map = Stream.of(new Object[][] { 
             { index,  lastSymbol}
            }).collect(Collectors.toMap(data -> (Integer) data[0], data -> (Character) data[1]));
        }
        map.putAll(extractPunctuationMap(index + 1, parts));
        return map;
    }
    
    private static String generate(int index, String[] parts, Map<Integer, Character> punctuationMap) {
        
        if (index >= parts.length) {
            return "";
        }
        String part = index == 0? " " + parts[index] : parts[index];
        if (punctuationMap.containsKey(parts.length -1 - index)) {
            part += punctuationMap.get(parts.length -1 - index);
        }
        return generate(index + 1, parts, punctuationMap) + part;
        
    }
}

In pseudocode maybe something like that:在伪代码中可能是这样的:

  1. take the whole sentence把整个句子

(a). (一个)。 get the first word得到第一个词

(b). (b)。 get the last word得到最后一句话

(if there is a punctuation after the first or last word, leave it there) (如果第一个或最后一个单词后有标点符号,请留在那里)

  1. swap(a, b) and return the remaining middle of the sentence交换(a,b)并返回句子的剩余中间部分
  2. repeat (1) and (2) until there is only two words or one重复(1)和(2)直到只有两个词或一个
  3. return the last two (swapped) words left (if one word, just return that)返回剩下的最后两个(交换的)单词(如果是一个单词,就返回那个)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM