84 votes

Équivalent Java de l'implode PHP(',' , array_filter( array () ))

J'utilise souvent ce morceau de code en PHP

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

Il efface les chaînes vides et les joint avec un ",". S'il n'en reste qu'une, il n'ajoute pas de virgule supplémentaire inutile. Il n'ajoute pas de virgule à la fin. S'il n'en reste aucune, il renvoie une chaîne vide.

Je peux donc obtenir l'un des résultats suivants

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

Quelle est la meilleure implémentation Java (moins de code) en Java ? sans avoir à ajouter des bibliothèques externes (conception pour Android) ?

101voto

Pshemo Points 34648

Version mise à jour utilisant Java 8 (original à la fin de l'article)

Si vous n'avez pas besoin de filtrer des éléments, vous pouvez utiliser


Depuis Java 8, nous pouvons utiliser StringJoiner (au lieu de l'utilisation initiale de StringBulder ) et de simplifier notre code.
De même, pour éviter de recompiler " *" dans chaque appel de matches(" *") nous pouvons créer un modèle distinct qui conservera sa version compilée dans un champ et l'utilisera en cas de besoin.

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

Avec les flux, notre code peut ressembler à ce qui suit.

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

Si nous utilisons des flux, nous pouvons filter les éléments qui Predicate . Dans ce cas, nous voulons que le prédicat accepte les chaînes qui ne sont pas uniquement des espaces - en d'autres termes, la chaîne doit contenir un caractère autre qu'un espace blanc.

Nous pouvons créer un tel prédicat à partir d'un motif. Le prédicat ainsi créé acceptera toutes les chaînes de caractères qui contiennent des sous-chaînes pouvant être couvertes par la regex (ainsi, si la regex recherche "\\S" Le prédicat accepte les chaînes de caractères telles que "foo " , " foo bar " , "whatever" mais n'acceptera pas " " ni " " ).

Nous pouvons donc utiliser

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

ou peut-être un peu plus descriptif, négation des chaînes de caractères qui ne sont que des espaces, ou vides

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

Ensuite, lorsque le filtre éliminera toutes les chaînes vides ou ne contenant que des espaces, nous pourrons collect le reste des éléments. Grâce à Collectors.joining nous pouvons décider du délimiteur à utiliser.


Réponse originale (avant 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();
}

Vous pouvez l'utiliser comme

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

ou

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

Sortie ab, abs

80voto

Bogdan Burim Points 3658

Pourquoi tant de sérieux ? Essayer StringUtils.join(new String[] {"Hello", "World", "!"}, ", ") !

20voto

MoleFole Points 224

Voici une réponse spécifique à Android qui pourrait être utile à certains :

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

// Result => Red,Green,Blue

Veillez à importer la classe TextUtils :

import android.text.TextUtils;

17voto

nickb Points 37850

Vous devez ajouter vos chaînes à une liste de tableaux, supprimer celles qui sont vides et les formater en conséquence :

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

En outre, si vous aviez String[] un tableau de chaînes de caractères, vous pouvez facilement les ajouter à une liste de tableaux (ArrayList) :

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

3voto

Aman J Points 328

Utilisation des flux (pour Java 8 et suivantes) serait une autre solution possible.

Vous devez importer

java.util.stream.Collectors;

pour utiliser la procédure de jonction

Vous pouvez utiliser :

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

pour obtenir le résultat souhaité.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X