À partir d'une liste
List<String> l = new ArrayList<String>();
l.add("one");
l.add("two");
l.add("three");
J'ai une méthode
String join(List<String> messages) {
if (messages.isEmpty()) return "";
if (messages.size() == 1) return messages.get(0);
String message = "";
message = StringUtils.join(messages.subList(0, messages.size() -2), ", ");
message = message + (messages.size() > 2 ? ", " : "") + StringUtils.join(messages.subList(messages.size() -2, messages.size()), ", and ");
return message;
}
qui, pour l, produit "un, deux et trois" . Ma question est la suivante: existe-t-il une méthode standard (Apache-commons) qui fait la même chose?, par exemple
WhatEverUtils.join(l, ", ", ", and ");
Clarifier. Mon problème est que cette méthode ne fonctionne pas. Cela fonctionne comme je le veux, c'est testé et tout va bien. Mon problème est que je ne pouvais pas trouver un module similaire à Apache-commons qui implémente une telle fonctionnalité. Ce qui me surprend, je ne peux pas être le premier à en avoir besoin.
Mais alors peut-être que tout le monde vient de faire
StringUtils.join(l, ", ").replaceAll(lastCommaRegex, ", and");
En Java 8, vous pouvez utiliser String.join()
comme suit:
Collection<String> elements = ....;
String result = String.join(", ", elements);
Qu'en est-il join from: org.Apache.commons.lang.StringUtils
Exemple:
StringUtils.join(new String[] { "one", "two", "three" }, ", "); // one, two, three
Pour avoir "et" ou ", et" vous pouvez simplement remplacer la dernière virgule.
J'aime utiliser les collections Google à cette fin. Propre et très utile:
Joiner.on(",").join(myList)
Ce type de code a été écrit maintes et maintes fois et vous devriez plutôt être libéré pour implémenter votre logique d’implémentation spécifique.
Si vous utilisez maven, voici la dépendance:
<dependency>
<groupId>com.google.collections</groupId>
<artifactId>google-collections</artifactId>
<version>1.0</version>
</dependency>
Il a aussi beaucoup d'autres fonctionnalités intéressantes!
EDIT: Par souci d’exhaustivité, cela produira la liste "un, deux et trois".
List<String> originalList = Arrays.asList("one", "two", "three");
Joiner.on(", ").join(originalList.subList(0, originalList.size() - 1))
.concat(", and ").concat(originalList.get(originalList.size() - 1));
Avec Java 8, vous pouvez utiliser des flux avec des membres.
Collection<String> strings;
...
String commaDelimited = strings.stream().collect(Collectors.joining(","));
// use strings.parallelStream() instead, if you think
// there are gains to be had by doing fork/join
D'autres réponses parlent de "remplacer la dernière virgule", ce qui n'est pas sûr si le dernier terme contient lui-même une virgule.
Plutôt que d'utiliser une bibliothèque, vous pouvez simplement utiliser une ligne (bien que longue) de code JDK:
public static String join(List<String> msgs) {
return msgs == null || msgs.size() == 0 ? "" : msgs.size() == 1 ? msgs.get(0) : msgs.subList(0, msgs.size() - 1).toString().replaceAll("^.|.$", "") + " and " + msgs.get(msgs.size() - 1);
}
Voir une démonstration live de ce code traitant tous les cas Edge.
Pour votre information, voici deux lignes plus lisibles:
public static String join(List<String> msgs) {
int size = msgs == null ? 0 : msgs.size();
return size == 0 ? "" : size == 1 ? msgs.get(0) : msgs.subList(0, --size).toString().replaceAll("^.|.$", "") + " and " + msgs.get(size);
}
Pour produire une sortie grammaticale en anglais, vous devez prendre en compte trois cas lors de la concaténation d'une liste de chaînes:
"UNE"
"A et B"
"A, B et C.
Ceci peut être accompli en utilisant Java ou Guava standard comme ci-dessous. Les solutions sont fondamentalement les mêmes et vous permettent de choisir ce que vous voulez utiliser.
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
import Java.util.List;
import static org.junit.Assert.assertEquals;
public class JoinListTest {
@Test
public void test_join() {
// create cases (don't need to use ImmutableList builder from guava)
final List<String> case1 = new ImmutableList.Builder<String>().add("A").build();
final List<String> case2 = new ImmutableList.Builder<String>().add("A", "B").build();
final List<String> case3 = new ImmutableList.Builder<String>().add("A", "B", "C").build();
// test with standard Java
assertEquals("A", joinListGrammaticallyWithJava(case1));
assertEquals("A and B", joinListGrammaticallyWithJava(case2));
assertEquals("A, B, and C", joinListGrammaticallyWithJava(case3));
// test with guava
assertEquals("A", joinListGrammaticallyWithGuava(case1));
assertEquals("A and B", joinListGrammaticallyWithGuava(case2));
assertEquals("A, B, and C", joinListGrammaticallyWithGuava(case3));
}
private String joinListGrammaticallyWithJava(final List<String> list) {
return list.size() > 1
? String.join(", ", list.subList(0, list.size() - 1))
.concat(String.format("%s and ", list.size() > 2 ? "," : ""))
.concat(list.get(list.size() - 1))
: list.get(0);
}
private String joinListGrammaticallyWithGuava(final List<String> list) {
return list.size() > 1
? Joiner.on(", ").join(list.subList(0, list.size() - 1))
.concat(String.format("%s and ", list.size() > 2 ? "," : ""))
.concat(list.get(list.size() - 1))
: list.get(0);
}
}
Je ne connais pas de menuisier Apache String pouvant prendre en charge l'ajout de and
dans la chaîne jointe.
Voici un code non testé qui fera ce que vous avez demandé:
public static String join(String separator, List<String> mList, boolean includeAndInText) {
StringBuilder sb = new StringBuilder();
int count = 0;
for (String m: mList) {
if (includeAndInText && (count + 1 != mList.size())) {
sb.append (" and ");
}
sb.append(m);
count++;
if (count < mList.size()) {
sp.append(separator);
}
}
return sb.toString();
}