首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从文本中分析言语

从文本中分析言语
EN

Code Review用户
提问于 2016-04-02 20:13:42
回答 1查看 88关注 0票数 3

我正在做一个实验,用文字角色扮演游戏(MUD)中的一个表情来解析语音,这样如果你听不清,或者是用另一种语言,你就不会理解它。这是正确的,但我只是想确保它是尽可能清晰和有效的。

代码语言:javascript
复制
import java.util.Scanner;
import java.util.Random;

public class EmoteParser {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter an emote: ");
        String emote = scanner.nextLine();

        System.out.println("Original emote:\n" + emote);
        System.out.println("\nParsed emote:\n" + jumbleEmoteSpeech(emote));
    }

    public static String jumbleEmoteSpeech(String emote) {
        StringBuilder out = new StringBuilder();
        int quote1Location = emote.indexOf('"');

        if (quote1Location == -1) {
            out.append(emote);
        }
        else {
            int quote2Location;
            int currentIndex = 0;
            boolean found = true;
            do {
                quote2Location = emote.indexOf('"', quote1Location + 1);
                if (quote2Location == -1 || quote2Location < currentIndex) {
                    out.append(emote.substring(currentIndex));
                    found = false;
                }
                else {
                    out.append(emote.substring(currentIndex, quote1Location + 1));
                    out.append(jumble(emote.substring(quote1Location + 1, quote2Location)));
                    currentIndex = quote2Location;

                    quote1Location = emote.indexOf('"', currentIndex + 1);
                }
            } while (found);
        }

        return out.toString();
    }

    public static String jumble(String text) {
        StringBuilder out = new StringBuilder();
        Random generator = new Random();

        for (int i = 0; i < text.length(); i++) {
            char ch = text.charAt(i);
            if (Character.isLetter(ch)) {
                if (Character.isUpperCase(ch)) {
                    out.append((char)('A' + generator.nextInt(26)));
                }
                else {
                    out.append((char)('a' + generator.nextInt(26)));
                }
            }
            else if (Character.isDigit(ch)) {
                out.append((char)('0' + generator.nextInt(10)));
            }
            else {
                out.append(text.charAt(i));
            }
        }

        return out.toString();
    }
}

另外,使用'"'"\""有什么真正的好处吗?我认为'"'的可读性更强,而且任何性能差异都可能得到优化。

EN

回答 1

Code Review用户

回答已采纳

发布于 2016-04-02 21:20:09

jumble方法

jumble方法中,通过索引从0到输入数组的长度来遍历字符。

代码语言:javascript
复制
for (int i = 0; i < text.length(); i++) {
    char ch = text.charAt(i);
    // ...
}

由于除了检索字符之外,您不使用索引,所以您只需使用toCharArray()并直接对字符进行循环:

代码语言:javascript
复制
for (char ch : text.toCharArray()) {
    // ...
}

然后,您将根据字符的代码点追加字符。为此,你要做的就是

代码语言:javascript
复制
out.append((char) ('A' + generator.nextInt(26))); // same for 'a' and '0'

您可以直接使用appendCodePoint,而不是使用这种(丑陋的)强制转换

代码语言:javascript
复制
out.appendCodePoint('A' + generator.nextInt(26));

此外,混淆字符的代码路径可能会导致潜在的错误:

代码语言:javascript
复制
if (Character.isLetter(ch)) {
    if (Character.isUpperCase(ch)) {
        // ...
    } else {
        // ...
    }
} else if (Character.isDigit(ch)) {
    // ...
} else {
    // ...
}

问题是,对于不仅是大写或小写字符的字符,isLetter返回true。例如,对于按照Unicode分类为"Lo“的所有那些奇怪的角色 (以及OTHER_LETTER中的Java),它将返回true。它还将返回true for 那些机密的“Lm” (MODIFIER_LETTER in Java),如"OL CHIKI AHAD“ᱽ。例如,由于我认为,在希伯来字母"BET",ב的情况下,您不想将其视为小写(因为您的代码不是大写字母),所以您可以完全删除该检查,并拥有:

代码语言:javascript
复制
if (Character.isUpperCase(ch)) {
    sb.appendCodePoint('A' + generator.nextInt(26));
} else if (Character.isLowerCase(ch)) {
    sb.appendCodePoint('a' + generator.nextInt(26));
} else if (Character.isDigit(ch)) {
    sb.appendCodePoint('0' + generator.nextInt(10));
} else {
    sb.append(ch);
}

这样,在这些分支中只会考虑大小写(上或下)的字符。但是,有很多小写字母 (和大写字母)与a-z不同,比如ῲ或ⅎ,甚至ⱙ(这显然是"GLAGOLITIC小写字母IOTATED大YUS")。在这种情况下,它们将被拉丁文小字符取代,这可能是你想要的,也可能不是你想要的。如果你真的只想混淆拉丁字母,最好用'a''z'来测试字符(大写字母相反)。你知道吗?这不仅仅是字母。有很多数字不是0-9,比如٨(阿拉伯文8)或᧗(New 7),甚至꧓(显然是Javanese 3)。因此,如果您只想专注于拉丁字母和罗马数字,您可以只使用

代码语言:javascript
复制
if (ch >= 'A' && ch <= 'Z') {
    sb.appendCodePoint('A' + generator.nextInt(26));
} else if (ch >= 'a' && ch <= 'z') {
    sb.appendCodePoint('a' + generator.nextInt(26));
} else if (ch >= '0' && ch <= '9') {
    sb.appendCodePoint('0' + generator.nextInt(10));
} else {
    sb.append(ch);
}

最后一个问题是关于Random对象。每次执行此方法时都要创建一个。最好只创建一个每次都重复使用相同的。例如,可以有一个常量。

代码语言:javascript
复制
private static final Random RANDOM = new Random();

jumbleEmoteSpeech方法

在可能的情况下,您应该总是希望尽早从方法中返回。在这种情况下,如果字符串中没有引号,则可以不加更改地返回它。

代码语言:javascript
复制
StringBuilder out = new StringBuilder();
int quote1Location = emote.indexOf('"');
if (quote1Location == -1) {
    out.append(emote);
} else {
    // ...
}
return out.toString();

你可以用更简洁的方式写这个

代码语言:javascript
复制
int quote1Location = emote.indexOf('"');
if (quote1Location == -1) {
    return emote;
}
// ...

这完成了两件事:

  • 没有创建StringBuilder:我们不需要一个
  • 代码的可读性更强,因为不再需要else部件:它用一个缩进来移动其余部分。

此外,更喜欢在使用时声明变量。在本例中,您在int quote2Location;循环之前声明while

代码语言:javascript
复制
int quote2Location;
do {
    quote2Location = emote.indexOf('"', quote1Location + 1);
    // ...
} while (...);

相反,你可以拥有:

代码语言:javascript
复制
do {
    int quote2Location = emote.indexOf('"', quote1Location + 1);
    // ...
} while (...);
票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/124577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档