首页 > 解决方案 > 仅提取第一次出现的字符以及连字符前后的所有数字

问题描述

我遇到这种情况来编写一个通用函数,它只能从字符串中提取字符的第一次出现和所有数字。

输入字符串(说):ABC123-45DEF-GH67IJ9
输出字符串:A123-45D-G679

我已经敲定了一种方法,但程序的复杂性很高。这里对我来说有两种不好的情况:

  1. 我的程序输出不正确。
    输出: A123-45D-G679-(这个额外的连字符是下面代码中的问题)。
  2. 我需要一种更好的方法来以不太复杂的方式完成这项工作。

这是我的代码片段:

package Test;

import java.util.LinkedList;

public class FirstLetterAndNumerics {

    static void firstLetterAndNumber(String string) {

        StringBuffer sb = new StringBuffer();
        LinkedList<String> ll = new LinkedList<String>();
        String[] str = string.split("-");
        boolean flag = true;

        for (int i = 0; i < str.length; i++) {

            ll.add(str[i]);
        }
        for (int j = 0; j < ll.size(); j++) {

            if (Character.isAlphabetic(ll.get(j).charAt(0))) {
                if (flag == false) {
                    sb.append("-");
                }
                sb.append(ll.get(j).charAt(0));

                for (int k = 1; k < ll.get(j).length(); k++) {
                    if (Character.isAlphabetic(ll.get(j).charAt(k))) {
                        flag = false;
                    } else if (Character.isDigit(ll.get(j).charAt(k))) {
                        sb.append(ll.get(j).charAt(k));
                    }
                }
                sb.append("-");
                flag = true;
            } else if (Character.isDigit(ll.get(j).charAt(0))) {
                sb.append(ll.get(j).charAt(0));

                for (int l = 1; l < ll.get(j).length(); l++) {

                    if (Character.isDigit(ll.get(j).charAt(l))) {
                        sb.append(ll.get(j).charAt(l));
                    } else if (Character.isAlphabetic(ll.get(j).charAt(l)) && flag == true) {
                        sb.append(ll.get(j).charAt(l));
                        flag = false;
                    }

                }
            }

        }
        System.out.println(sb);

    }

    public static void main(String[] args) {

        firstLetterAndNumber("ABC123-45DEF-GH67IJ9");
    }
}

标签: javaregexstringstringbuffer

解决方案


您在连字符的开头拆分字符串。要确保字符串包含由连字符分隔的大写字符和数字,您可以首先使用:

if(string.matches("[A-Z0-9]+(?:-[A-Z0-9]+)+")) {

正则表达式演示

然后您可以使用 2 个捕获组并使用该\G模式。

(?:(\b[0-9]*[A-Z])|\G(?!^))[A-Z]*([0-9]*)

那将匹配

  • (?:非捕获组
    • (捕获组 1
      • \b[0-9]*[A-Z]字边界,匹配 0+ 个数字和单个字符 AZ
    • )关闭组 1
    • |或者
    • \G(?!^)在上一场比赛结束时断言位置,而不是在开始时
  • )关闭非捕获组
  • [A-Z]*匹配 0+ 个字符 AZ
  • ([0-9]*)捕获组 2,匹配 0+ 位

在替换中使用 2 个捕获组$1$2

正则表达式演示| Java 演示

例如

static void firstLetterAndNumber(String string) {
    if(string.matches("[A-Z0-9]+(?:-[A-Z0-9]+)+")) {
        Pattern pattern = Pattern.compile("(?:(\\b\\d*[A-Z])|\\G(?!^))[A-Z]*(\\d*)");
        Matcher matcher = pattern.matcher(string);
        System.out.println(matcher.replaceAll("$1$2");

    }
}

运行firstLetterAndNumber("ABC123-45DEF-GH67IJ9");会输出

A123-45D-G679

推荐阅读