繁体   English   中英

将字符串拆分为字符串数组

[英]Split string into array of character strings

我需要将一个字符串拆分为一个单字符字符串数组。

例如,拆分“cat”将得到数组“c”、“a”、“t”

"cat".split("(?!^)")

这将产生

数组 ["c", "a", "t"]

"cat".toCharArray()

但是如果你需要字符串

"cat".split("")

编辑:这将返回一个空的第一个值。

String str = "cat";
char[] cArray = str.toCharArray();

如果输入中需要超出基本多语言平面的字符(一些 CJK 字符、新的表情符号...),则不能使用诸如"a💫b".split("(?!^)")之类的方法,因为它们会破坏这些字符(结果到array ["a", "?", "?", "b"] )并且必须使用更安全的东西:

"a💫b".codePoints()
    .mapToObj(cp -> new String(Character.toChars(cp)))
    .toArray(size -> new String[size]);

如果字符串包含代理对, split("(?!^)")无法正常工作。 您应该使用split("(?<=.)")

String[] splitted = "花ab🌹🌺🌷".split("(?<=.)");
System.out.println(Arrays.toString(splitted));

输出:

[花, a, b, 🌹, 🌺, 🌷]

总结其他答案......

这适用于所有 Java 版本:

"cat".split("(?!^)")

这仅适用于 Java 8 及更高版本:

"cat".split("")

将字符串转换为单字符字符串数组的一种有效方法是执行以下操作:

String[] res = new String[str.length()];
for (int i = 0; i < str.length(); i++) {
    res[i] = Character.toString(str.charAt(i));
}

但是,这并没有考虑到String中的char实际上可以表示 Unicode 代码点的一半这一事实。 (如果代码点不在 BMP 中。)要解决这个问题,您需要遍历代码点……这更复杂。

这种方法将比使用String.split(/* clever regex*/)更快,并且可能比使用 Java 8+ 流更快。 它可能比这更快:

String[] res = new String[str.length()];
int 0 = 0;
for (char ch: str.toCharArray[]) {
    res[i++] = Character.toString(ch);
}  

因为toCharArray必须字符复制到新数组中。

for(int i=0;i<str.length();i++)
{
System.out.println(str.charAt(i));
}

在我之前的回答中,我混淆了 JavaScript。这里是对 Java 的性能分析。

我同意需要关注 Java String 中的 Unicode Surrogate Pairs。 这打破了像String.length()这样的方法的意义,甚至打破了Character的功能意义,因为它最终是一个技术性的 object,它可能不代表人类语言中的一个字符。

我实现了 4 种方法,将字符串拆分为字符表示字符串列表( String s 对应于字符s 的人类含义)。 这是比较的结果:

一行是一个String ,由 1000 个任意选择的表情符号和 1000 个 ASCII 字符组成(1000 次<emoji><ascii> ,人类意义上总共 2000 个“字符”)。

不同分裂方式的比较

(丢弃 256 和 512 措施) 在此处输入图像描述

实施:

  • 代码点(java 11 及以上)
    public static List<String> toCharacterStringListWithCodePoints(String str) {
        if (str == null) {
            return Collections.emptyList();
        }
        return str.codePoints()
            .mapToObj(Character::toString)
            .collect(Collectors.toList());
    }
  • 经典的
    public static List<String> toCharacterStringListWithIfBlock(String str) {
        if (str == null) {
            return Collections.emptyList();
        }
        List<String> strings = new ArrayList<>();
        char[] charArray = str.toCharArray();
        int delta = 1;
        for (int i = 0; i < charArray.length; i += delta) {
            delta = 1;
            if (i < charArray.length - 1 && Character.isSurrogatePair(charArray[i], charArray[i + 1])) {
                delta = 2;
                strings.add(String.valueOf(new char[]{ charArray[i], charArray[i + 1] }));
            } else {
                strings.add(Character.toString(charArray[i]));
            }
        }
        return strings;
    }
  • 正则表达式
    static final Pattern p = Pattern.compile("(?<=.)");
    public static List<String> toCharacterStringListWithRegex(String str) {
        if (str == null) {
            return Collections.emptyList();
        }
        return Arrays.asList(p.split(str));
    }

附件(原始数据):

codePoints;classic;regex;lines
45;44;84;256
14;20;98;512
29;42;91;1024
52;56;99;2048
87;121;174;4096
175;221;375;8192
345;411;839;16384
667;826;1285;32768
1277;1536;2440;65536
2426;2938;4238;131072

如果原始字符串包含补充 Unicode 字符,则split()将不起作用,因为它将这些字符拆分为代理对。 为了正确处理这些特殊字符,这样的代码有效:

String[] chars = new String[stringToSplit.codePointCount(0, stringToSplit.length())];
for (int i = 0, j = 0; i < stringToSplit.length(); j++) {
    int cp = stringToSplit.codePointAt(i);
    char c[] = Character.toChars(cp);
    chars[j] = new String(c);
    i += Character.charCount(cp);
}

也许您可以使用 for 循环遍历字符串内容并使用charAt方法逐个字符提取字符。

例如,结合ArrayList<String> ,您可以获得单个字符的数组。

我们可以简单地做到这一点

const string = 'hello';
console.log([...string]); // -> ['h','e','l','l','o']

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

展开语法 (...) 允许扩展诸如数组表达式或字符串之类的可迭代对象...

因此,字符串可以非常简单地扩展为字符数组。

暂无
暂无

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

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