Câu hỏi Cách chia chuỗi trong Java


Tôi có một chuỗi, "004-034556", mà tôi muốn chia thành hai chuỗi:

string1=004
string2=034556

Điều đó có nghĩa là chuỗi đầu tiên sẽ chứa các ký tự trước '-'và chuỗi thứ hai sẽ chứa các ký tự sau '-'. Tôi cũng muốn kiểm tra xem chuỗi có '-' trong đó. Nếu không, tôi sẽ ném một ngoại lệ. Tôi có thể làm cái này như thế nào?


1280
2017-08-14 03:01


gốc


hỏi cùng một câu hỏi ngay bây giờ sẽ dẫn đến lũ lượt bỏ phiếu phủ định - Bharat Mukkala
id thay vì tìm kiếm google / stackoverflow hơn đọc javadocs - Reece Markowsky


Các câu trả lời:


Chỉ cần sử dụng phương pháp thích hợp: String#split().

String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556

Lưu ý rằng điều này cần biểu hiện thông thường, vì vậy hãy nhớ thoát ký tự đặc biệt Nếu cần.

ở đó 12 ký tự có ý nghĩa đặc biệt: dấu gạch chéo ngược \, dấu mũ ^, ký hiệu đô la $, dấu chấm hoặc dấu chấm ., thanh dọc hoặc biểu tượng ống |, dấu chấm hỏi ?, dấu hoa thị hoặc dấu sao *, dấu cộng +, dấu mở ngoặc (, dấu ngoặc đơn đóng )và khung hình vuông mở [, mở ngoặc nhọn {Những ký tự đặc biệt này thường được gọi là "siêu ký tự".

Vì vậy, nếu bạn muốn chia nhỏ, ví dụ: dấu chấm / chấm . nghĩa là "bất kỳ nhân vật nào"trong regex, hãy sử dụng dấu gạch chéo ngược \ để thoát khỏi nhân vật đặc biệt như vậy split("\\."), hoặc dùng lớp nhân vật [] để đại diện cho nhân vật theo nghĩa đen như vậy split("[.]"), hoặc dùng Pattern#quote() để thoát khỏi toàn bộ chuỗi như vậy split(Pattern.quote(".")).

String[] parts = string.split(Pattern.quote(".")); // Split on period.

Để kiểm tra trước nếu chuỗi chứa một số ký tự nhất định, chỉ cần sử dụng String#contains().

if (string.contains("-")) {
    // Split it.
} else {
    throw new IllegalArgumentException("String " + string + " does not contain -");
}

Lưu ý, điều này không có biểu thức chính quy. Cho rằng, sử dụng String#matches() thay thế.

Nếu bạn muốn giữ lại ký tự phân tách trong các phần kết quả, thì hãy sử dụng lạc quan tích cực. Trong trường hợp bạn muốn có ký tự phân tách để kết thúc ở phía bên trái, hãy sử dụng lookbehind tích cực bằng cách thêm tiền tố ?<= nhóm trên mẫu.

String string = "004-034556";
String[] parts = string.split("(?<=-)");
String part1 = parts[0]; // 004-
String part2 = parts[1]; // 034556

Trong trường hợp bạn muốn có ký tự phân tách để kết thúc ở phía bên phải, hãy sử dụng lookahead dương bằng cách thêm tiền tố ?= nhóm trên mẫu.

String string = "004-034556";
String[] parts = string.split("(?=-)");
String part1 = parts[0]; // 004
String part2 = parts[1]; // -034556

Nếu bạn muốn giới hạn số lượng các phần kết quả, thì bạn có thể cung cấp số mong muốn làm đối số thứ 2 của split() phương pháp.

String string = "004-034556-42";
String[] parts = string.split("-", 2);
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556-42

2349
2017-08-14 03:05



Tại sao bạn sử dụng các ký hiệu băm để phân định các phương thức của String? - Crowie
@Crowie: javadoc-phong cách. - BalusC
Trường hợp góc: nếu không thể tìm thấy reugalr expression nó trả về một mảng phần tử với toàn bộ chuỗi. - mklimek
Pattern.quote những gì tôi đang tìm :) - Dev911


Một cách khác để xử lý chuỗi trực tiếp sẽ là sử dụng cụm từ thông dụng với các nhóm chụp. Điều này có lợi thế là nó làm cho nó đơn giản để ngụ ý những ràng buộc phức tạp hơn về đầu vào. Ví dụ, sau đây chia chuỗi thành hai phần, và đảm bảo rằng cả hai chỉ bao gồm các chữ số:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

class SplitExample
{
    private static Pattern twopart = Pattern.compile("(\\d+)-(\\d+)");

    public static void checkString(String s)
    {
        Matcher m = twopart.matcher(s);
        if (m.matches()) {
            System.out.println(s + " matches; first part is " + m.group(1) +
                               ", second part is " + m.group(2) + ".");
        } else {
            System.out.println(s + " does not match.");
        }
    }

    public static void main(String[] args) {
        checkString("123-4567");
        checkString("foo-bar");
        checkString("123-");
        checkString("-4567");
        checkString("123-4567-890");
    }
}

Khi mẫu được cố định trong trường hợp này, nó có thể được biên dịch trước và được lưu trữ như một thành viên tĩnh (được khởi tạo ở thời gian tải lớp trong ví dụ). Cụm từ thông dụng là:

(\d+)-(\d+)

Các dấu ngoặc đơn biểu thị các nhóm chụp; chuỗi khớp với phần đó của regexp có thể được truy cập bằng phương thức Match.group (), như được hiển thị. Các \ d đối sánh và một chữ số thập phân, và + có nghĩa là "khớp một hoặc nhiều biểu thức trước đó). - Không có ý nghĩa đặc biệt, vì vậy chỉ khớp với ký tự đó trong đầu vào. Lưu ý rằng bạn cần phải thoát kép các dấu gạch chéo ngược khi viết như một chuỗi Java. Một số ví dụ khác:

([A-Z]+)-([A-Z]+)          // Each part consists of only capital letters 
([^-]+)-([^-]+)            // Each part consists of characters other than -
([A-Z]{2})-(\d+)           // The first part is exactly two capital letters,
                           // the second consists of digits

68
2017-08-14 11:28



Đây là một giải pháp tuyệt vời, tuy nhiên phần đầu tiên phải là m.group(1), phần thứ hai m.group(2), kể từ đó m.group(0) thực sự trả lại mẫu phù hợp hoàn chỉnh. Tôi nghĩ tôi cũng nhớ group(0) đã từng là trận đấu đầu tiên thay vì kiểu đầy đủ, có thể điều này đã thay đổi trong bản cập nhật phiên bản java gần đây. - ptstone
Cảm ơn. Nhìn docs.oracle.com/javase/7/docs/api/java/util/regex/…, bạn đúng - phù hợp với hầu hết các thư viện regexp khác, nhóm 0 là toàn bộ, và các nhóm đã bắt đầu bắt đầu lúc 1. Như bạn nói, tôi nghi ngờ rằng điều này có thể đã thay đổi kể từ khi tôi viết câu trả lời, nhưng trong bất kỳ trường hợp tôi sẽ cập nhật nó để phản ánh hành vi hiện tại. - Rob Hague


String[] result = yourString.split("-");
if (result.length != 2) 
     throw new IllegalArgumentException("String not in correct format");

Điều này sẽ chia chuỗi của bạn thành 2 phần. Phần tử đầu tiên trong mảng sẽ là phần chứa nội dung trước -và phần tử thứ 2 trong mảng sẽ chứa một phần của chuỗi của bạn sau -.

Nếu chiều dài mảng không phải là 2, thì chuỗi không có định dạng: string-string.

Kiểm tra split() phương pháp trong String lớp học.

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int-


39
2017-08-14 03:06



Điều này sẽ chấp nhận "-555" làm đầu vào và trả về [, 555]. Các yêu cầu không được xác định rõ ràng, nếu nó có giá trị để chấp nhận điều này. Tôi khuyên bạn nên viết một số bài kiểm tra đơn vị để xác định hành vi mong muốn. - Michael Konietzka
Thực sự an toàn nhất để thay đổi (result.length! = 2) thành (result.length <2) - Uncle Iroh


// This leaves the regexes issue out of question
// But we must remember that each character in the Delimiter String is treated
// like a single delimiter        

public static String[] SplitUsingTokenizer(String subject, String delimiters) {
   StringTokenizer strTkn = new StringTokenizer(subject, delimiters);
   ArrayList<String> arrLis = new ArrayList<String>(subject.length());

   while(strTkn.hasMoreTokens())
      arrLis.add(strTkn.nextToken());

   return arrLis.toArray(new String[0]);
}

26
2017-11-16 06:30



JavaDoc nêu rõ: "StringTokenizer là một lớp kế thừa được giữ lại vì lý do tương thích mặc dù việc sử dụng nó không được khuyến khích trong mã mới. Đó là khuyến cáo rằng bất cứ ai tìm kiếm chức năng này sử dụng split phương pháp của String hoặc là java.util.regex thay vào đó. " - bvdb


String[] out = string.split("-");

nên làm điều bạn muốn. Lớp chuỗi có nhiều phương thức để hoạt động với chuỗi.


23
2017-08-14 03:06





Các yêu cầu còn lại để giải thích. Tôi khuyên bạn nên viết một phương pháp,

public final static String[] mySplit(final String s)

đóng gói chức năng này. Tất nhiên bạn có thể sử dụng String.split (..) như đã đề cập trong các câu trả lời khác để thực hiện.

Bạn nên viết một số bài kiểm tra đơn vị cho các chuỗi đầu vào và các kết quả và hành vi mong muốn.

Ứng cử viên thi tốt nên bao gồm:

 - "0022-3333"
 - "-"
 - "5555-"
 - "-333"
 - "3344-"
 - "--"
 - ""
 - "553535"
 - "333-333-33"
 - "222--222"
 - "222--"
 - "--4555"

Với việc xác định kết quả kiểm tra theo, bạn có thể xác định hành vi.

Ví dụ, nếu "-333" nên quay lại [,333] hoặc nếu đó là lỗi. Có thể "333-333-33" được tách ra trong [333,333-33] or [333-333,33] hoặc là một lỗi? Và cứ thế.


17
2017-08-14 06:57



Lời khuyên hữu ích, nhưng không thực sự là câu trả lời cho câu hỏi. Nếu bạn đang hỗ trợ một câu trả lời khác với chi tiết thì chú thích sẽ được ưu tiên hơn. - Chris Mountford


Giả sử răng

  • bạn không thực sự cần cụm từ thông dụng cho phần tách
  • bạn tình cờ đã sử dụng apache commons lang trong ứng dụng của bạn

Cách dễ nhất là sử dụng StringUtils # split (java.lang.String, char). Đó là thuận tiện hơn so với một được cung cấp bởi Java ra khỏi hộp nếu bạn không cần biểu thức thông thường. Giống như hướng dẫn sử dụng của nó nói, nó hoạt động như thế này:

A null input String returns null.

 StringUtils.split(null, *)         = null
 StringUtils.split("", *)           = []
 StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
 StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
 StringUtils.split("a:b:c", '.')    = ["a:b:c"]
 StringUtils.split("a b c", ' ')    = ["a", "b", "c"]

Tôi khuyên bạn nên sử dụng commong-lang, vì thường nó chứa rất nhiều thứ có thể sử dụng được. Tuy nhiên, nếu bạn không cần nó cho bất cứ điều gì khác hơn là làm một chia, sau đó thực hiện chính mình hoặc thoát regex là một lựa chọn tốt hơn.


15
2018-03-25 06:43





Sử dụng org.apache.commons.lang.StringUtils ' phương pháp tách có thể chia chuỗi dựa trên ký tự hoặc chuỗi bạn muốn tách.

Chữ ký phương thức:

public static String[] split(String str, char separatorChar);

Trong trường hợp của bạn, bạn muốn tách một chuỗi khi có dấu "-".

Bạn chỉ cần làm như sau:

String str = "004-034556";

String split[] = StringUtils.split(str,"-");

Đầu ra:

004
034556

Giả sử rằng nếu - không tồn tại trong chuỗi của bạn, nó trả về chuỗi đã cho và bạn sẽ không nhận được bất kỳ ngoại lệ nào.


15
2017-07-01 04:35