Java tương đương với implode của PHP (',', array_filter (array ()))


75

Tôi thường sử dụng đoạn mã này trong PHP

$ordine['address'] = implode(', ', array_filter(array($cliente['cap'], $cliente['citta'], $cliente['provincia'])));

Nó xóa các chuỗi trống và nối chúng bằng dấu ",". Nếu chỉ còn lại thì nó không thêm dấu phẩy thừa không cần thiết. Nó không thêm dấu phẩy ở cuối. Nếu không còn nó, nó sẽ trả về chuỗi trống.

Vì vậy, tôi có thể nhận được một trong các kết quả sau

""
"Street abc 14"
"Street abc 14, 00168"
"Street abc 14, 00168, Rome"

Cách triển khai Java tốt nhất (ít mã hơn) trong Java mà không cần phải thêm thư viện bên ngoài (thiết kế cho Android) là gì?



FYI đối với ví dụ đó, bạn sẽ cần một thư viện bên ngoài (import org.apache.commons.lang.StringUtils;) nhưng tôi vẫn khuyên bạn nên sử dụng phương pháp đó
owen gerig

dfreeman không làm những gì tôi cần, không có dấu phẩy thêm nơi cần thiết
max4ever

4
không thể tin rằng java chưa có cái này được tích hợp sẵn. mọi ngôn ngữ khác đều có.
OneSolitaryNoob

Bạn có thể vui lòng thay đổi dấu chấp nhận không? stackoverflow.com/a/11248692/871050 câu trả lời này là đúng nhất ở đây.
Madara's Ghost

Câu trả lời:


90

Phiên bản cập nhật sử dụng Java 8 (bản gốc ở cuối bài đăng)

Nếu bạn không cần lọc bất kỳ phần tử nào, bạn có thể sử dụng


Kể từ Java 8, chúng tôi có thể sử dụng StringJoiner(thay vì sử dụng ban đầu StringBulder) và đơn giản hóa mã của chúng tôi.
Ngoài ra, để tránh biên dịch lại " *"regex trong mỗi lần gọi, matches(" *")chúng ta có thể tạo Mẫu riêng biệt sẽ giữ phiên bản đã biên dịch của nó trong một số trường và sử dụng nó khi cần thiết.

private static final Pattern SPACES_OR_EMPTY = Pattern.compile(" *");
public static String implode(String separator, String... data) {
    StringJoiner sb = new StringJoiner(separator);
    for (String token : data) {
        if (!SPACES_OR_EMPTY.matcher(token).matches()) {
            sb.add(token);
        }
    }
    return sb.toString();
}   

Với các luồng, mã của chúng tôi có thể trông như thế nào.

private static final Predicate<String> IS_NOT_SPACES_ONLY = 
        Pattern.compile("^\\s*$").asPredicate().negate();

public static String implode(String delimiter, String... data) {
    return Arrays.stream(data)
            .filter(IS_NOT_SPACES_ONLY)
            .collect(Collectors.joining(delimiter));
}

Nếu chúng tôi sử dụng các luồng, chúng tôi có thể filteryếu tố đó Predicate. Trong trường hợp này, chúng ta muốn vị từ chấp nhận các chuỗi không chỉ là khoảng trắng - nói cách khác chuỗi phải chứa ký tự không phải khoảng trắng.

Chúng ta có thể tạo Predicate như vậy từ Pattern. Vị ngữ tạo ra theo cách này sẽ chấp nhận bất kỳ chuỗi đó sẽ chứa chuỗi có thể được kết hợp bởi regex (vì vậy nếu regex sẽ tìm kiếm "\\S"vị sẽ chấp nhận chuỗi như "foo ", " foo bar ", "whatever", nhưng sẽ không chấp nhận " "và cũng không " ").

Vì vậy, chúng ta có thể sử dụng

Pattern.compile("\\S").asPredicate();

hoặc có thể mô tả nhiều hơn một chút, phủ định của các chuỗi chỉ là khoảng trắng hoặc trống

Pattern.compile("^\\s*$").asPredicate().negate();

Tiếp theo khi bộ lọc sẽ loại bỏ tất cả các chuỗi trống hoặc chỉ chứa khoảng trắng Các chuỗi chúng ta có thể collectcòn lại các phần tử. Nhờ Collectors.joiningchúng tôi có thể quyết định sử dụng dấu phân cách nào.


Câu trả lời gốc (trước Java 8)

public static String implode(String separator, String... data) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < data.length - 1; i++) {
    //data.length - 1 => to not add separator at the end
        if (!data[i].matches(" *")) {//empty string are ""; " "; "  "; and so on
            sb.append(data[i]);
            sb.append(separator);
        }
    }
    sb.append(data[data.length - 1].trim());
    return sb.toString();
}

Bạn có thể sử dụng nó như

System.out.println(implode(", ", "ab", " ", "abs"));

hoặc là

System.out.println(implode(", ", new String[] { "ab", " ", "abs" }));

Đầu ra ab, abs


vâng đó là thoải mái hơn để sử dụng kể từ khi bạn không cần phải tạo ra một mảng, và tôi không biết bạn có thể sử dụng String, String ...
max4ever

nó không hoạt động tốt khi dữ liệu có độ dài 1 xD Tôi sử dụng sb.append này (data [0]); for (int i = 1; i <(data.length); i ++) {//data.length - 1 => để không thêm dấu phân tách ở cuối if ((data [i]! = null) &&! data [i ] .matches ("*")) {// chuỗi trống là ""; ""; ""; và như vậy sb.append (dấu phân cách); sb.append (data [i]); }}
max4ever

1
@ max4ever bạn có thể chỉ ra một số ví dụ không? Tôi đã thử nghiệm System.out.println(implode(", ", "X"))và nó nối hoạt động tốt.
Pshemo

79

Sao căng thẳng vậy? Cố gắng StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")!


30
StringUtils là một thư viện bên ngoài
max4ever

28
nó được thực hiện bởi Apache, tất cả mọi người sử dụng nó ... Tôi đang làm nó theo cách Bogdan của, các bạn làm những gì bạn muốn
anton1980

10
Bạn đang "làm theo cách của mình", nếu thư viện đã có sẵn. Nếu không, a) bạn cần biết rằng nó là bên ngoài b) bạn có thể lấy nó ở đâu / bằng cách nào và c) bạn có được phép làm như vậy không. Chơi cao bồi không phải của công ty chỉ giúp bạn giải tỏa c)
Zefiro

3
Thư viện bên ngoài có thể được tìm thấy tại đây: commons.apache.org/proper/commons-lang
Alan B. Dee

19

Đây là câu trả lời dành riêng cho Android có thể hữu ích cho một số người:

String combined = TextUtils.join(",", new String[]{"Red", "Green", "Blue"});

// Result => Red,Green,Blue

Đảm bảo nhập lớp TextUtils:

import android.text.TextUtils;

17

Bạn phải thêm chuỗi của mình vào ArrayList, xóa những chuỗi trống và định dạng nó cho phù hợp:

public static String createAddressString( String street, String zip_code, String country) {
    List<String> list = new ArrayList<String>();
    list.add( street);
    list.add( zip_code);
    list.add( country);

    // Remove all empty values
    list.removeAll(Arrays.asList("", null));

    // If this list is empty, it only contained blank values
    if( list.isEmpty()) {
        return "";
    }

    // Format the ArrayList as a string, similar to implode
    StringBuilder builder = new StringBuilder();
    builder.append( list.remove(0));

    for( String s : list) {
        builder.append( ", ");
        builder.append( s);
    }

    return builder.toString();
}

Ngoài ra, nếu bạn có String[], một mảng chuỗi, bạn có thể dễ dàng thêm chúng vào ArrayList:

String[] s;
List<String> list = new ArrayList<String>( Arrays.asList( s));

Trong quá trình triển khai hàm implode, bạn sửa đổi danh sách ban đầu (sai) và bạn loại bỏ phần tử đầu tiên của ArrayList (tốn kém). Ngoài ra, chuyển đổi được đề xuất từ ​​mảng - tại sao không chỉ asList? Dù sao, nếu đầu vào là một Danh sách, thì cách tốt nhất để tự làm điều đó có lẽ là sử dụng trình lặp của danh sách với việc đọc (và thêm) phần tử đầu tiên trước chu kỳ, sau đó lặp lại phần còn lại. Xin lỗi, nhưng tôi phải cho bạn -1.
Vlasec

Đối với việc loại bỏ các chuỗi rỗng và chuỗi rỗng, bạn cũng có thể xóa chúng khỏi đầu ra mà không cần sửa đổi danh sách ban đầu - nhưng tất nhiên bạn sẽ cần một chu trình để tìm phần tử không rỗng đầu tiên chứ không phải đơn giản nếu. Ngoài ra, giải pháp của bạn không thành công trên một danh sách trống - hãy remove(0)ném một IndexOutOfBoundsException.
Vlasec

@Vlasec - Không có danh sách gốc, trong phương pháp này, tôi tạo danh sách cục bộ của riêng mình, vì vậy đối số của bạn không hợp lệ, vì đầu vào không phải là danh sách mà là ba giá trị Chuỗi. Ngoài ra, có một kiểm tra nếu danh sách trống, đó là một đối số không hợp lệ khác mà bạn đã trình bày.
nickb

Bạn đúng kỹ thuật. Tuy nhiên, bạn vẫn nên cố gắng dạy những cách thực hành tốt nhất tại đây. Một số greenhorn có thể áp dụng kỹ thuật của bạn và làm rối tung danh sách hiện có. Thêm vào đó, nó không phải là một cách tiếp cận đặc biệt hiệu quả hoặc thanh lịch ngay cả khi bạn có thể phá hủy bộ sưu tập.
Vlasec

@Vlasec - Bạn có quyền đưa ra ý kiến ​​của mình, tuy nhiên tôi không đồng ý. Nhận xét của bạn rằng đó không phải là một giải pháp hiệu quả hoặc thanh lịch chỉ dựa trên quan điểm.
nickb

2

Một Implode đơn giản

public static String implode(String glue, String[] strArray)
{
    String ret = "";
    for(int i=0;i<strArray.length;i++)
    {
        ret += (i == strArray.length - 1) ? strArray[i] : strArray[i] + glue;
    }
    return ret;
}

Bạn có thể tạo quá tải cho nó ..

Ở trên nó tương đương với php implode.
Đây là những gì bạn muốn:

import java.lang.*
public static String customImplode(String glue, String[] strArray)
{
    String ret = "";
    for(int i=0;i<strArray.length;i++)
    {
        if (strArray[i].trim() != "")
            ret += (i == strArray.length - 1) ? strArray[i] : strArray[i] + glue;
    }
    return ret;
}

2
nó cho biết thêm keo để kết thúc, và nó không bỏ qua chuỗi rỗng
max4ever

@ max4ever Tôi nghĩ đây là câu trả lời của bạn, phải không?
Soroush Khosravi

vẫn không bỏ qua các chuỗi trống
max4ever

@ max4ever Vui lòng xóa câu hỏi của bạn. Bạn muốn một phương thức tùy chỉnh hoặc phương thức tương đương của php implode?! \
Soroush Khosravi

bạn cần thêm (TextUtils.isEmpty (strArray [i])? "": strArray [i] + keo để làm cho nó hoạt động
max4ever

2

Sử dụng Luồng (dành cho Java 8 trở lên) sẽ là một giải pháp khả thi thay thế cho việc này.

Bạn bắt buộc phải nhập

java.util.stream.Collectors;

để sử dụng quá trình tham gia

Bạn có thể sử dụng:

Arrays.asList("foo","bar").stream().collect(Collectors.joining(","));

để đạt được kết quả mong muốn.


1

Đây là cách triển khai mã hóa của tôi:

/**
 * Implodes the specified items, gluing them using the specified glue replacing nulls with the specified
 * null placeholder.
 * @param glue              The text to use between the specified items.
 * @param nullPlaceholder   The placeholder to use for items that are <code>null</code> value.
 * @param items             The items to implode.
 * @return  A <code>String</code> containing the items in their order, separated by the specified glue.
 */
public static final String implode(String glue, String nullPlaceholder, String ... items) {
    StringBuilder sb = new StringBuilder();
    for (String item : items) {
        if (item != null) {
            sb.append(item);
        } else {
            sb.append(nullPlaceholder);
        }
        sb.append(glue);
    }
    return sb.delete(sb.length() - glue.length(), sb.length()).toString();
}

1
public static String implode(List<String> items, String separator) {

        if (items == null || items.isEmpty()) {
            return null;
        }
        String delimiter = "";
        StringBuilder builder = new StringBuilder();
        for (String item : items) {
            builder.append(delimiter).append(item);
            delimiter = separator;
        }
        return builder.toString();
    }

Một lời giải thích sẽ được theo thứ tự.
Peter Mortensen

0

Sử dụng chức năng đơn giản này:

private String my_implode(String spacer, String[] in_array){

    String res = "";

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

        if (!res.equals("")) {
            res += spacer;
        }
        res += in_array[i];
    }

    return res;
}

Sử dụng:

data_arr = {"d1", "d2", "d3"};
your_imploded_text = my_implode(",", data_arr);
// Output: your_imploded_text = "d1,d2,d3"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.