简体   繁体   English

setCharAt方法无法在for循环内正常工作(Java)

[英]setCharAt method not working as expected inside for loop (Java)

I am trying to develop a method to reverse the vowels in a string. 我正在尝试开发一种方法来反转字符串中的元音。 For this, I have developed my own small stack. 为此,我开发了自己的小型堆栈。 I am iterating backwards through the string twice, once to populate the stack with each vowel I locate, the second time to replace the vowel with the vowel stored at the top of the stack. 我在字符串中向后迭代两次,一次是用我找到的每个元音填充堆栈,第二次是用存储在堆栈顶部的元音替换该元音。 I have added a bunch of print statements to determine where this is failing and it seems to be failing at the setCharAt method. 我添加了一堆打印语句来确定这在哪里失败,并且在setCharAt方法上似乎失败了。 For testing purposes, I provide a string aeiou and I am expecting to get back uoiea . 出于测试目的,我提供了一个字符串aeiou并且我希望返回uoiea The chars are getting replaced during each iteration, but unfortunately, they don't stay that way. 这些字符在每次迭代期间都会被替换,但是不幸的是,它们并没有保持这种状态。 As of the next iteration, the chars that were replaced on the previous iteration return to what they were before. 从下一次迭代开始,在上一次迭代中替换的字符恢复到之前的状态。 As a result, I am getting back ueiou , where only the first character in the string is as expected (and the third which is a noop). 结果,我回到了ueiou ,其中只有字符串中的第一个字符是预期的(第三个字符是noop)。 Here is my code. 这是我的代码。 Any tips are appreciated. 任何提示表示赞赏。

import java.util.*;

public class Solution {

    static String result;

    static class StackOfVowels {
        static Node top;

        public StackOfVowels() {
            Node top = null;
        }

        static class Node {
            Node next = null; 
            char vowel = '\0';
            Node(char value) {
                this.vowel = value;
            }
        }

        public void push(char item) {
            Node node = new Node(item);
            if (top == null) {
                top = node;
            }
            else { 
                node.next = top;
                top = node;
            }
        }

        public char top() {
            if (top == null) throw new EmptyStackException();
            return top.vowel; 
        }

        public void pop() {
            int result = -1;
            if (top != null) {
                result = top.vowel;
                top = top.next;
            }
        }
    }

    public static String reverseVowels(String s) {

        StackOfVowels stackOfVowels = new StackOfVowels();

        for(int i = s.length()-1; i >= 0; i--) {
            char c = s.charAt(i);
            if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
                System.out.println("Initial sequence of iterations identified vowel: " + c);
                stackOfVowels.push(c);
                System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
            }
        }

        for(int j = s.length()-1; j >= 0; j--) {
            char b = s.charAt(j);
            if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
                System.out.println("Second sequence of iterations identified vowel: " + b);
                StringBuilder newstr = new StringBuilder(s);
                char d = stackOfVowels.top();
                System.out.println("Variable d set to top of: " + stackOfVowels.top());
                newstr.setCharAt(j, d);
                result = newstr.toString();
                System.out.println("Here is the new string: " + result);
                stackOfVowels.pop();
                System.out.println("Stack was popped");
            }
        }
        return result;
    }

    public static void main(String[] args) {
        String s = "aeiou";
        reverseVowels(s);
        System.out.println("Final result: " + result);
    }
}

You generate always a new StringBuilder in your second loop with StringBuilder newstr = new StringBuilder(s); 在第二个循环中,您总是使用StringBuilder生成一个新的StringBuilder StringBuilder newstr = new StringBuilder(s); But you always use ´s´ and not ´result´ to build your new StringBuilder. 但是,您始终使用“ s”而非“ result”来构建新的StringBuilder。

It would be better anyways to not create a new Object of StringBuilder in each Iteration. 无论如何,最好不要在每个迭代中创建StringBuilder的新对象。

Also it is confusing that your methode has a return value, which is never used. 同样令人困惑的是,您的方法有一个返回值,从未使用过。

Following methode should work: 以下方法应该起作用:

public static String reverseVowels(String s) {

    StackOfVowels stackOfVowels = new StackOfVowels();

    for(int i = s.length()-1; i >= 0; i--) {
        char c = s.charAt(i);
        if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
            System.out.println("Initial sequence of iterations identified vowel: " + c);
            stackOfVowels.push(c);
            System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
        }
    }
    StringBuilder result_builder = new StringBuilder(s);
    for(int j = s.length()-1; j >= 0; j--) {
        char b = s.charAt(j);

        if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
            System.out.println("Second sequence of iterations identified vowel: " + b);
            char d = stackOfVowels.top();
            System.out.println("Variable d set to top of: " + stackOfVowels.top());
            result_builder.setCharAt(j, d);
            stackOfVowels.pop();
            System.out.println("Stack was popped");
        }
    }
    result = result_builder.toString();
    return result_builder.toString();
}

I would approach the problem a little differently, first I would use a regular expression to remove all consonants from the String to create a String of vowels . 我将以不同的方式处理该问题,首先,我将使用正则表达式String删除所有辅音,以创建一个vowels String Then I would iterate through the characters of the String , using StringBuilder to build the output (passing consonants through, but replacing vowels using the vowels String previously created). 然后,我将使用StringBuilder遍历String的字符,以构建输出(传递辅音,但使用先前创建的vowels String替换元音)。 Like, 喜欢,

public static String reverseVowels(String s) {
    // Match all consonants, and remove them. Reverse that String.
    String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
            .reverse().toString();
    StringBuilder sb = new StringBuilder();
    for (int i = 0, p = 0; i < s.length(); i++) {
        switch (Character.toLowerCase(s.charAt(i))) {
        // Note that these fall-through...
        case 'a': case 'e': case 'i': case 'o': case 'u':
            sb.append(vowels.charAt(p++));
            break;
        default:
            sb.append(s.charAt(i));
        }
    }
    return sb.toString();
}

This is one of the places that switch and fall-through behavior can be taken advantage of. 这是可以利用switch和掉线行为的地方之一。

And if you're using Java 8+, you could express the same with an IntStream and map the characters; 如果您使用的是Java 8+,则可以使用IntStream表示相同的IntStream并映射字符。 like 喜欢

String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
        .reverse().toString();
int[] counter = new int[1]; // <-- A bit of a kludge really.
return IntStream.range(0, s.length()).mapToObj(i -> {
    switch (Character.toLowerCase(s.charAt(i))) {
    case 'a': case 'e': case 'i': case 'o': case 'u':
        return Character.toString(vowels.charAt(counter[0]++));
    default:
        return Character.toString(s.charAt(i));
    }
}).collect(Collectors.joining());

A slight improvement (debatable) on @Elliot answer is to create the StringBuilder with the original String and only replace when necessary @Elliot答案的一个小改进(值得商))是使用原始String创建StringBuilder并仅在必要时替换

    String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
            .reverse().toString();
    StringBuilder sb = new StringBuilder(s);
    for (int i = 0, p = 0; i < s.length(); i++) {
        switch (Character.toLowerCase(s.charAt(i))) {
        // Note that these fall-through...
        case 'a': case 'e': case 'i': case 'o': case 'u':
            sb.setCharAt(i, vowels.charAt(p++));
            break;
        default:
            break;
        }
    }
    return sb.toString();

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

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