Xóa các ký tự đứng đầu và theo sau khỏi chuỗi

1. Giới thiệu

Trong hướng dẫn ngắn này, chúng ta sẽ thấy một số cách để xóa các ký tự đầu và cuối khỏi một Chuỗi . Để đơn giản, chúng tôi sẽ loại bỏ các số 0 trong các ví dụ.

Với mỗi lần triển khai, chúng tôi sẽ tạo hai phương pháp: một phương thức cho số 0 ở đầu và một phương thức cho các số 0 ở cuối.

Bài toán này có một trường hợp cạnh: chúng ta muốn làm gì, khi đầu vào chỉ chứa các số 0? Trả về một Chuỗi trống hay một Chuỗi chứa một số 0? Chúng tôi sẽ thấy các triển khai cho cả hai trường hợp sử dụng trong mỗi giải pháp.

Chúng tôi có các bài kiểm tra đơn vị cho từng triển khai, bạn có thể tìm thấy trên GitHub.

2. Sử dụng StringBuilder

Trong giải pháp đầu tiên của chúng tôi, chúng tôi sẽ tạo một StringBuilder với Chuỗi ban đầu và chúng tôi sẽ xóa các ký tự không cần thiết từ đầu hoặc cuối:

String removeLeadingZeroes(String s) { StringBuilder sb = new StringBuilder(s); while (sb.length() > 0 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.toString(); } String removeTrailingZeroes(String s) { StringBuilder sb = new StringBuilder(s); while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '0') { sb.setLength(sb.length() - 1); } return sb.toString(); }

Lưu ý rằng chúng tôi sử dụng StringBuilder.setLength () thay vì StringBuilder.deleteCharAt () khi chúng tôi xóa các số 0 ở cuối vì nó cũng xóa một số ký tự cuối cùng và nó hoạt động hiệu quả hơn.

Nếu chúng ta không muốn trả về một Chuỗi trống khi đầu vào chỉ chứa các số 0, điều duy nhất chúng ta cần làm là dừng vòng lặp nếu chỉ còn một ký tự duy nhất .

Do đó, chúng tôi thay đổi điều kiện vòng lặp:

String removeLeadingZeroes(String s) { StringBuilder sb = new StringBuilder(s); while (sb.length() > 1 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.toString(); } String removeTrailingZeroes(String s) { StringBuilder sb = new StringBuilder(s); while (sb.length() > 1 && sb.charAt(sb.length() - 1) == '0') { sb.setLength(sb.length() - 1); } return sb.toString(); }

3. Sử dụng String.subString ()

Trong giải pháp này khi chúng ta loại bỏ các số 0 ở đầu hoặc ở cuối, chúng ta sẽ tìm thấy vị trí của ký tự khác 0 đầu tiên hoặc cuối cùng.

Sau đó, chúng ta chỉ phải gọi chuỗi con () , để trả về các phần còn lại:

String removeLeadingZeroes(String s) { int index; for (index = 0; index = 0; index--) { if (s.charAt(index) != '0') { break; } } return s.substring(0, index + 1); }

Lưu ý rằng chúng ta phải khai báo chỉ số biến trước vòng lặp for vì chúng ta muốn sử dụng biến bên ngoài phạm vi của vòng lặp.

Cũng lưu ý rằng chúng ta phải tìm kiếm các ký tự khác 0 theo cách thủ công, vì String.indexOf ()String.lastIndexOf () chỉ hoạt động để đối sánh chính xác.

Nếu chúng ta không muốn trả về một Chuỗi trống , chúng ta phải làm tương tự như trước: thay đổi điều kiện vòng lặp :

String removeLeadingZeroes(String s) { int index; for (index = 0; index  0; index--) { if (s.charAt(index) != '0') { break; } } return s.substring(0, index + 1); }

4. Sử dụng Apache Commons

Apache Commons có nhiều lớp hữu ích, bao gồm org.apache.commons.lang.StringUtils . Nói chính xác hơn, lớp này nằm trong Apache Commons Lang3.

4.1. Sự phụ thuộc

Chúng tôi có thể sử dụng Apache Commons Lang3 bằng cách chèn phụ thuộc này vào tệp pom.xml của chúng tôi :

 org.apache.commons commons-lang3 3.8.1 

4.2. Thực hiện

Trong lớp StringUtils , chúng ta có các phương thức stripStart ()dảiEnd () . Họ loại bỏ các ký tự đầu và cuối tương ứng.

Vì đó chính xác là những gì chúng ta cần, giải pháp của chúng tôi khá đơn giản:

String removeLeadingZeroes(String s) { return StringUtils.stripStart(s, "0"); } String removeTrailingZeroes(String s) { return StringUtils.stripEnd(s, "0"); }

Thật không may, chúng tôi không thể định cấu hình, nếu chúng tôi muốn xóa tất cả các lần xuất hiện hay không. Do đó, chúng ta cần kiểm soát nó bằng tay.

Nếu đầu vào không trống, nhưng chuỗi bị tước là trống, thì chúng ta phải trả về chính xác một số 0:

String removeLeadingZeroes(String s) { String stripped = StringUtils.stripStart(s, "0"); if (stripped.isEmpty() && !s.isEmpty()) { return "0"; } return stripped; } String removeTrailingZeroes(String s) { String stripped = StringUtils.stripEnd(s, "0"); if (stripped.isEmpty() && !s.isEmpty()) { return "0"; } return stripped; }

Lưu ý rằng các phương thức này chấp nhận một Chuỗi làm tham số thứ hai của chúng. Chuỗi này đại diện cho một tập hợp các ký tự, không phải một chuỗi mà chúng ta muốn loại bỏ.

Ví dụ: nếu chúng ta vượt qua “01” , chúng sẽ loại bỏ bất kỳ ký tự đầu hoặc cuối nào, là '0' hoặc '1' .

5. Sử dụng Ổi

Ổi cũng cung cấp nhiều lớp tiện ích. Đối với vấn đề này, chúng ta có thể sử dụng com.google.common.base.CharMatcher , cung cấp các phương thức tiện ích để tương tác với các ký tự phù hợp.

5.1. Sự phụ thuộc

Để sử dụng Guava, chúng ta nên thêm các phần phụ thuộc sau vào tệp pom.xml của chúng tôi :

 com.google.guava guava 27.0.1-jre 

Lưu ý rằng nếu chúng ta muốn sử dụng Guava trong ứng dụng Android, chúng ta nên sử dụng phiên bản 27.0-android để thay thế.

5.2. Thực hiện

Trong trường hợp của chúng tôi, chúng tôi quan tâm đến trimLeadingFrom ()trimTrailingFrom () .

Như tên gọi của chúng cho thấy, chúng loại bỏ bất kỳ ký tự đầu hoặc cuối nào tương ứng khỏi một Chuỗi , khớp với CharMatcher :

String removeLeadingZeroes(String s) { return CharMatcher.is('0').trimLeadingFrom(s); } String removeTrailingZeroes(String s) { return CharMatcher.is('0').trimTrailingFrom(s); }

Chúng có các đặc điểm giống như các phương pháp Apache Commons mà chúng ta đã thấy.

Do đó, nếu không muốn xóa tất cả các số 0, chúng ta có thể sử dụng thủ thuật tương tự:

String removeLeadingZeroes(String s) { String stripped = CharMatcher.is('0').trimLeadingFrom(s); if (stripped.isEmpty() && !s.isEmpty()) { return "0"; } return stripped; } String removeTrailingZeroes(String s) { String stripped = CharMatcher.is('0').trimTrailingFrom(s); if (stripped.isEmpty() && !s.isEmpty()) { return "0"; } return stripped; }

Lưu ý rằng với CharMatcher, chúng ta có thể tạo các quy tắc đối sánh phức tạp hơn.

6. Sử dụng Cụm từ Thông dụng

Vì vấn đề của chúng tôi là vấn đề đối sánh mẫu, chúng tôi có thể sử dụng biểu thức chính quy: chúng tôi muốn so khớp tất cả các số 0 ở đầu hoặc cuối của một chuỗi .

Trên hết, chúng tôi muốn xóa những số 0 trùng khớp đó. Nói cách khác, chúng ta muốn thay thế chúng bằng không, hay nói cách khác, là một Chuỗi trống .

Chúng ta có thể làm chính xác điều đó, với phương thức String.replaceAll () :

String removeLeadingZeroes(String s) { return s.replaceAll("^0+", ""); } String removeTrailingZeroes(String s) { return s.replaceAll("0+$", ""); }

Nếu không muốn loại bỏ tất cả các số 0, chúng ta có thể sử dụng cùng một giải pháp mà chúng ta đã sử dụng với Apache Commons và Guava. Tuy nhiên, có một cách thuần túy về biểu thức chính quy để làm điều này: chúng ta phải cung cấp một mẫu, không khớp với toàn bộ Chuỗi .

Bằng cách đó, nếu đầu vào chỉ chứa các số 0, thì công cụ regexp sẽ giữ chính xác một số không phù hợp. Chúng ta có thể làm điều này với các mẫu sau:

String removeLeadingZeroes(String s) { return s.replaceAll("^0+(?!$)", ""); } String removeTrailingZeroes(String s) { return s.replaceAll("(?!^)0+$", ""); }

Lưu ý rằng “(?! ^)”“(?! $)” Có nghĩa là nó không phải là đầu hoặc cuối của chuỗi tương ứng.

7. Kết luận

Trong hướng dẫn này, chúng tôi đã thấy một số cách để xóa các ký tự đầu và cuối khỏi Chuỗi . Sự lựa chọn giữa các triển khai này thường chỉ đơn giản là sở thích cá nhân.

Như thường lệ, các ví dụ có sẵn trên GitHub.