Java等价于PHP的implode(',',array_filter(array()))


75

我经常在PHP中使用这段代码

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

它清除空字符串,并用“,”将其连接。如果仅剩一个,它不会添加多余的逗号。它不会在末尾添加逗号。如果没有,则返回空字符串。

因此,我可以获得以下结果之一

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

在Java中无需添加外部库(针对Android设计)的最佳Java实现(更少的代码)是什么?



仅供参考,对于该示例,您将需要一个外部库(导入org.apache.commons.lang.StringUtils;),但是我仍然建议使用该方法
owig gerig 2012年

dfreeman不执行我需要的操作,在需要的地方不添加逗号
max4ever 2012年

4
不敢相信Java还没有内置此功能。其他所有语言都可以。
OneSolitaryNoob

您可以更改接受标记吗?stackoverflow.com/a/11248692/871050这个答案在这里是最正确的。
马达拉的鬼魂

Answers:


90

使用Java 8的更新版本(发布后的原始版本)

如果您不需要过滤任何元素,则可以使用


从Java 8开始,我们可以使用StringJoiner(而不是最初使用StringBulder)并简化我们的代码。
另外,为了避免" *"在每次调用中重新编译正则表达式,matches(" *")我们可以创建单独的Pattern,该Pattern将在某些字段中保留其编译版本,并在需要时使用它。

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();
}   

通过流,我们的代码看起来像。

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));
}

如果我们使用流,则可以filter包含哪些元素Predicate。在这种情况下,我们希望谓词接受不仅是空格的字符串-换句话说,字符串必须包含非空白字符。

我们可以从Pattern中创建这样的谓词。谓词创建这样将接受其中将包含子这可以通过正则表达式匹配任何字符串(所以,如果正则表达式将寻找"\\S"谓词会接受像琴弦"foo "" foo bar ""whatever",但不会接受" "也不是" ")。

所以我们可以使用

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

或更具描述性,否定字符串(只能为空格或为空)

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

接下来,当filter将删除所有空的或仅包含空格的字符串时,我们可以collect其余元素。多亏了Collectors.joining我们可以决定使用哪个定界符。


原始答案(在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();
}

你可以像这样使用它

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

要么

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

输出量 ab, abs


是的,因为您不必创建数组,所以使用起来更舒服,而且我不知道您可以使用String,String ...
max4ever 2012年

当数据长度为1 xD时,它不能很好地工作,我使用了sb.append(data [0]); for(int i = 1; i <(data.length); i ++){//data.length-1 =>如果(((data [i]!= null)&&!data [i ] .matches(“ *”)){//空字符串是“”; “”; “”; 等等sb.append(separator); sb.append(data [i]); }
max4ever 2012年

1
@ max4ever您能举个例子吗?我进行了测试,发现System.out.println(implode(", ", "X"))它工作正常。
Pshemo

79

为什么那么认真?试试看StringUtils.join(new String[] {"Hello", "World", "!"}, ", ")


30
StringUtils是一个外部库
max4ever 2013年

28
它是由Apache制成的,每个人都在使用它...我正在按照Bogdan的方式,你们做您想做的事
anton1980

10
如果该库已经可用,则您可以“按自己的方式做”。如果不是,则a)您需要知道它是外部的b)在何处/如何获得它,以及c)是否被允许这样做。扮演非公司牛仔只会让您摆脱c)
Zefiro

3
外部库可以在这里找到:commons.apache.org/proper/commons-lang
Alan B. Dee

19

这是一个特定于Android的答案,可能对某些人有帮助:

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

// Result => Red,Green,Blue

确保导入TextUtils类:

import android.text.TextUtils;

17

您必须将字符串添加到ArrayList中,删除空字符串,并相应地设置其格式:

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();
}

此外,如果有String[]字符串数组,则可以轻松地将它们添加到ArrayList中:

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

在implode函数的实现中,您修改了原始列表(错误),并删除了ArrayList的第一个元素(costy)。另外,建议从数组转换-为什么不只是asList?无论如何,如果输入是列表,那么自己做的最干净的方法可能是使用列表的迭代器,并在循环前读取(并附加)第一个元素,然后迭代其余元素。抱歉,但我必须给您-1。
Vlasec

至于删除null和空字符串,您也可以在不修改原始列表的情况下将它们从输出中删除-但是,您当然需要一个循环来查找第一个非空元素,而不是简单的if。此外,您的解决方案在空列表上失败-remove(0)抛出IndexOutOfBoundsException
Vlasec

@Vlasec-我创建自己的本地列表的方法中没有原始列表,因此您的参数无效,因为输入的不是列表,而是三个String值。此外,还会检查列表是否为空,这是您提供的另一个无效参数。
nickb 2015年

您在技术上是正确的。但是,您仍然应该尝试在此处教授最佳做法。一些新角可能会采用您的技术并弄乱现有列表。另外,即使您可以销毁产品系列,也不是一种特别有效或优雅的方法。
Vlasec

@Vlasec-您有权发表自己的意见,但我不同意。您对它不是有效或优雅的解决方案的评论仅基于观点。
尼克

2

一个简单的信号

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;
}

您可以为其创建重载。

上面它相当于php内爆。
这是您想要的:

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
它会在最后添加胶水,并且不会跳过空字符串
max4ever 2012年

@ max4ever我认为这是您的答案,不是吗?
Soroush Khosravi 2012年

仍然不会跳过空字符串
max4ever 2012年

@ max4ever请清除您的问题。您想要自定义方法还是php implode的等效方法?!\
Soroush Khosravi 2012年

您需要添加(TextUtils.isEmpty(strArray [i])?“”:strArray [i] +胶水使其正常工作
max4ever 2012年

2

使用Streams(用于Java 8及更高版本)将是对此的另一种可能的解决方案。

您需要导入

java.util.stream.Collectors;

使用加入过程

您可以使用:

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

以达到预期的结果。


1

这是我的爆破实现:

/**
 * 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();
    }

一个解释将是有条理的。
Peter Mortensen

0

使用以下简单功能:

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;
}

采用:

data_arr = {"d1", "d2", "d3"};
your_imploded_text = my_implode(",", data_arr);
// Output: your_imploded_text = "d1,d2,d3"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.