2012-05-16 24 views
7

Tôi có chuỗi sau:
A:B:1111;domain:80;a;b
A là tùy chọn để B:1111;domain:80;a;b cũng là đầu vào hợp lệ.
Các :80 là không bắt buộc cũng vì vậy B:1111;domain;a;b hoặc :1111;domain;a;b cũng đầu vào hợp lệ
Những gì tôi muốn là để kết thúc với một String[] có:Cách tốt để tách chuỗi ở đây là gì?

s[0] = "A"; 
s[1] = "B"; 
s[2] = "1111"; 
s[3] = "domain:80" 
s[4] = "a" 
s[5] = "b" 

Tôi đã làm điều này như sau:

List<String> tokens = new ArrayList<String>(); 
String[] values = s.split(";"); 
String[] actions = values[0].split(":"); 

for(String a:actions){ 
    tokens.add(a); 
} 
//Start from 1 to skip A:B:1111 
for(int i = 1; i < values.length; i++){ 
    tokens.add(values[i]); 
} 
String[] finalResult = tokens.toArray(); 

Tôi đã tự hỏi là có một cách tốt hơn để làm điều này? Làm cách nào khác tôi có thể làm điều này hiệu quả hơn?

+1

bạn đã thử với: s.split ("[;:]") này chia regex cho một char đó là ' ; ' hoặc ':' – rascio

+0

Tên miền có luôn được theo sau là '80' không? – codaddict

+0

@codaddict: Không có tùy chọn nào cũng là – Jim

Trả lời

2

Không có nhiều mối quan tâm hiệu quả ở đây, tất cả tôi thấy là tuyến tính.

Dù sao, bạn có thể hoặc sử dụng cụm từ thông dụng hoặc bộ mã thông báo thủ công.

Bạn có thể tránh danh sách. Bạn biết chiều dài của valuesactions, vì vậy bạn có thể làm

String[] values = s.split(";"); 
String[] actions = values[0].split(":"); 
String[] result = new String[actions.length + values.length - 1]; 
System.arraycopy(actions, 0, result, 0, actions.legnth); 
System.arraycopy(values, 1, result, actions.length, values.length - 1); 
return result; 

Nó phải là một cách hợp lý hiệu quả, trừ khi bạn nhấn mạnh vào thực hiện split mình.

chưa được kiểm tra tiếp cận ở mức độ thấp (hãy chắc chắn để kiểm tra đơn vị và điểm chuẩn trước khi sử dụng):

// Separator characters, as char, not string. 
final static int s1 = ':'; 
final static int s2 = ';'; 
// Compute required size: 
int components = 1; 
for(int p = Math.min(s.indexOf(s1), s.indexOf(s2)); 
    p < s.length() && p > -1; 
    p = s.indexOf(s2, p+1)) { 
    components++; 
} 
String[] result = new String[components]; 
// Build result 
int in=0, i=0, out=Math.min(s.indexOf(s1), s.indexOf(s2)); 
while(out < s.length() && out > -1) { 
    result[i] = s.substring(in, out); 
    i++; 
    in = out + 1; 
    out = s.indexOf(s2, in); 
} 
assert(i == result.length - 1); 
result[i] = s.substring(in, s.length()); 
return result; 

Lưu ý: mã này được tối ưu hóa theo cách điên rồ của nó sẽ xem xét một : duy nhất trong phần đầu tiên . Xử lý thành phần cuối cùng hơi phức tạp, vì out sẽ có giá trị -1.

Tôi thường là không sử dụng cách tiếp cận cuối cùng này, trừ khi hiệu suất và bộ nhớ cực kỳ quan trọng. Nhiều khả năng vẫn còn một số lỗi trong đó, và mã là khá khó đọc, trong so sánh với một ở trên.

0

bạn có thể làm một cái gì đó giống như

String str = "A:B:1111;domain:80;a;b"; 
String[] temp; 

/* delimiter */ 
String delimiter = ";"; 
/* given string will be split by the argument delimiter provided. */ 
temp = str.split(delimiter); 
/* print substrings */ 
for(int i =0; i < temp.length ; i++) 
System.out.println(temp[i]); 
0

Trừ khi đây là một nút cổ chai trong mã của bạn và bạn đã xác minh rằng đừng lo lắng nhiều về hiệu quả như logic ở đây là hợp lý. Bạn có thể tránh tạo danh sách mảng tạm thời và thay vào đó tạo trực tiếp mảng khi bạn biết kích thước cần thiết.

+0

Tôi không biết nếu đây là hoặc sẽ là một nút cổ chai. Nhưng tôi cũng muốn học những cách khác để cải thiện – Jim

1

Với một số giả định về các ký tự có thể chấp nhận, regex này cung cấp xác thực cũng như chia thành các nhóm bạn mong muốn.

Pattern p = Pattern.compile("^((.+):)?(.+):(\\d+);(.+):(\\d+);(.+);(.+)$"); 
Matcher m = p.matcher("A:B:1111;domain:80;a;b"); 
if(m.matches()) 
{ 
    for(int i = 0; i <= m.groupCount(); i++) 
     System.out.println(m.group(i)); 
} 
m = p.matcher("B:1111;domain:80;a;b"); 
if(m.matches()) 
{ 
    for(int i = 0; i <= m.groupCount(); i++) 
     System.out.println(m.group(i)); 
} 

Cung cấp:

A:B:1111;domain:80;a;b // ignore this 
A: // ignore this 
A // This is the optional A, check for null 
B 
1111 
domain 
80 
a 
b 

B:1111;domain:80;a;b // ignore this 
null // ignore this 
null // This is the optional A, check for null 
B 
1111 
domain 
80 
a 
b 
0

Nếu bạn muốn giữ miền và cổng cùng nhau, thì tôi tin rằng bạn sẽ cần bạn sẽ cần hai phần tách. Bạn có thể làm điều đó với một số phép thuật regex, nhưng tôi sẽ nghi ngờ rằng bạn sẽ thấy bất kỳ lợi ích thực sự nào từ nó.

Nếu bạn không nhớ tách miền và cổng, sau đó:

String s= "A:B:1111;domain:80;a;b"; 
    List<String> tokens = new ArrayList<String>(); 
    String[] values = s.split(";|:"); 

    for(String a : values){ 
     tokens.add(a); 
    } 
Các vấn đề liên quan