【问题标题】:How to split a string between letters and digits (or between digits and letters)?如何在字母和数字之间(或在数字和字母之间)拆分字符串?
【发布时间】:2011-11-25 14:53:18
【问题描述】:

我正在尝试找出一种在 java 中拆分字符串的方法,该方法遵循如下模式:

String a = "123abc345def";

由此产生的结果应该如下:

x[0] = "123";
x[1] = "abc";
x[2] = "345";
x[3] = "def";

但是,我完全不知道如何实现这一目标。请问有人可以帮我吗?我曾尝试在网上搜索类似的问题,但是很难在搜索中正确表达。

请注意:字母和数字的数量可能会有所不同(例如,可能有一个像这样的字符串'1234a5bcdef')

【问题讨论】:

  • 我还没有尝试过任何东西 - 我什至不知道从哪里开始,因为这是我第一次遇到类似的问题。
  • 要求用户在所有关于作业问题的问题上添加“作业”标签。
  • @Michael 这不是一个“家庭作业”问题。我以前从来没有遇到过这种问题。
  • 这不是一个“家庭作业”问题,在某些情况下您需要这样做。
  • 我来找她是因为我正在寻找类似的解决方案。就我而言,我得到了一长串“规则”,并且必须在执行查找之前将它们拆分。

标签: java regex string


【解决方案1】:

您可以尝试在(?<=\D)(?=\d)|(?<=\d)(?=\D) 上进行拆分,例如:

str.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");

它匹配数字和非数字之间的位置(以任何顺序)。

  • (?&lt;=\D)(?=\d) - 匹配非数字 (\D) 和数字 (\d) 之间的位置
  • (?&lt;=\d)(?=\D) - 匹配数字和非数字之间的位置。

【讨论】:

  • 请记住,此解决方案会将既不是数字也不是字母的字符威胁为字母,因此您可能需要验证您的部件。
  • @TimPietzcker 我不是对这个问题投反对票的人——我从未见过它在 Java 中使用过,并且坦率地要求确认它在 Java 中是否有效。现在我什至赞成。
  • 使用[a-zA-Z] 而不是\\D 将保证匹配实际的文本字符。也适用于重音字符(例如 áü)
  • \D 适用于重音字符,[a-zA-Z] 不适用。如果要专门匹配 unicode “字母”,可以使用 \p{L}\p{L}\p{M}*
【解决方案2】:

怎么样:

private List<String> Parse(String str) {
    List<String> output = new ArrayList<String>();
    Matcher match = Pattern.compile("[0-9]+|[a-z]+|[A-Z]+").matcher(str);
    while (match.find()) {
        output.add(match.group());
    }
    return output;
}

【讨论】:

    【解决方案3】:

    你可以试试这个:

    Pattern p = Pattern.compile("[a-z]+|\\d+");
    Matcher m = p.matcher("123abc345def");
    ArrayList<String> allMatches = new ArrayList<>();
    while (m.find()) {
        allMatches.add(m.group());
    }
    

    结果 (allMatches) 将是:

    ["123", "abc", "345", "def"]
    

    【讨论】:

    • 这不是有效的 Java 语法。
    【解决方案4】:

    使用两种不同的模式:[0-9]*[a-zA-Z]*,并分别被它们分割两次。

    【讨论】:

    • 感谢您对此的帮助。我不确定我是否完全理解你的意思。请您更详细地解释一下或提供一个基本示例,以便我明白您的意思吗?
    • 从语义上讲,应该是 [0-9]+[a-zA-Z]+... 虽然它们会做同样的事情。
    • 首先将字符串拆分为数字模式并获取字符串数组,然后将字符串拆分为字母模式并获取数字数组。连接两个数组你会得到你想要的
    • @mishadoff:你必须交错数组,否则你会以错误的顺序得到元素。这是一种不必要的复杂情况,可以通过使用 Qtax 建议的正则表达式轻松避免。
    • 同意,Qtax 解决方案更好。
    【解决方案5】:

    如果您正在寻找不使用 Java String 功能(即splitmatch 等)的解决方案,那么以下内容应该会有所帮助:

    List<String> splitString(String string) {
            List<String> list = new ArrayList<String>();
            String token = "";
            char curr;
            for (int e = 0; e < string.length() + 1; e++) {
                if (e == 0)
                    curr = string.charAt(0);
                else {
                    curr = string.charAt(--e);
                }
    
                if (isNumber(curr)) {
                    while (e < string.length() && isNumber(string.charAt(e))) {
                        token += string.charAt(e++);
                    }
                    list.add(token);
                    token = "";
                } else {
                    while (e < string.length() && !isNumber(string.charAt(e))) {
                        token += string.charAt(e++);
                    }
                    list.add(token);
                    token = "";
                }
    
            }
    
            return list;
        }
    
    boolean isNumber(char c) {
            return c >= '0' && c <= '9';
        }
    

    此解决方案将拆分数字和“单词”,其中“单词”是不包含数字的字符串。但是,如果您希望只包含包含英文字母的“单词”,那么您可以通过添加更多条件(如 isNumber 方法调用)轻松修改它,具体取决于您的要求(例如,您可能希望跳过包含非英文字母的单词)。另请注意,splitString 方法返回 ArrayList,稍后可以将其转换为 String 数组。

    【讨论】:

    • 我喜欢你的代码,一句话:return c>= '0' && c
    【解决方案6】:

    很久没有使用Java了,所以只是一些伪代码,应该可以帮助您入门(对我来说比查找所有内容要快:))。

     string a = "123abc345def";
     string[] result;
     while(a.Length > 0)
     {
          string part;
          if((part = a.Match(/\d+/)).Length) // match digits
               ;
          else if((part = a.Match(/\a+/)).Length) // match letters
               ;
          else
               break; // something invalid - neither digit nor letter
          result.append(part);
          a = a.SubStr(part.Length - 1); // remove the part we've found
     }
    

    【讨论】:

      【解决方案7】:

      我正在为关键任务代码做这种事情。就像每一秒都很重要,因为我需要在不明显的时间内处理 180k 个条目。所以我跳过了正则表达式并完全拆分并允许对每个元素进行内联处理(尽管将它们添加到ArrayList&lt;String&gt; 会很好)。如果你想做这件事,但需要快 20 倍……

      void parseGroups(String text) {
          int last = 0;
          int state = 0;
          for (int i = 0, s = text.length(); i < s; i++) {
              switch (text.charAt(i)) {
                  case '0':
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                      if (state == 2) {
                          processElement(text.substring(last, i));
                          last = i;
                      }
                      state = 1;
                      break;
                  default:
                      if (state == 1) {
                          processElement(text.substring(last, i));
                          last = i;
                      }
                      state = 2;
                      break;
              }
          }
          processElement(text.substring(last));
      }
      

      【讨论】:

        【解决方案8】:

        这不 "d+|D+" 做这项工作而不是繁琐: "(?&lt;=\\D)(?=\\d)|(?&lt;=\\d)(?=\\D)" ?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多