String implémente Comparable, et c'est ce qu'est l'ordre naturel en Java (comparaison à l'aide de l'interface comparable). Vous pouvez placer les chaînes dans un TreeSet ou les trier à l'aide des classes Collections ou Arrays.
Cependant, dans votre cas, vous ne voulez pas d'un "classement naturel", mais plutôt d'un comparateur personnalisé, que vous pouvez ensuite utiliser dans la méthode Collections.sort ou la méthode Arrays.sort qui prend un comparateur.
En ce qui concerne la logique spécifique que vous cherchez à mettre en œuvre dans le comparateur (chiffres séparés par des points), je ne connais pas d'implémentation standard existante pour cela, mais comme vous l'avez dit, ce n'est pas un problème difficile.
EDIT : Dans votre commentaire, votre lien vous amène à aquí qui fait un bon travail si vous n'êtes pas gêné par le fait qu'il est sensible à la casse. Voici ce code modifié pour vous permettre de passer dans le fichier String.CASE_INSENSITIVE_ORDER
:
/*
* The Alphanum Algorithm is an improved sorting algorithm for strings
* containing numbers. Instead of sorting numbers in ASCII order like
* a standard sort, this algorithm sorts numbers in numeric order.
*
* The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
*
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
import java.util.Comparator;
/**
* This is an updated version with enhancements made by Daniel Migowski,
* Andre Bogus, and David Koelle
*
* To convert to use Templates (Java 1.5+):
* - Change "implements Comparator" to "implements Comparator<String>"
* - Change "compare(Object o1, Object o2)" to "compare(String s1, String s2)"
* - Remove the type checking and casting in compare().
*
* To use this class:
* Use the static "sort" method from the java.util.Collections class:
* Collections.sort(your list, new AlphanumComparator());
*/
public class AlphanumComparator implements Comparator<String>
{
private Comparator<String> comparator = new NaturalComparator();
public AlphanumComparator(Comparator<String> comparator) {
this.comparator = comparator;
}
public AlphanumComparator() {
}
private final boolean isDigit(char ch)
{
return ch >= 48 && ch <= 57;
}
/** Length of string is passed in for improved efficiency (only need to calculate it once) **/
private final String getChunk(String s, int slength, int marker)
{
StringBuilder chunk = new StringBuilder();
char c = s.charAt(marker);
chunk.append(c);
marker++;
if (isDigit(c))
{
while (marker < slength)
{
c = s.charAt(marker);
if (!isDigit(c))
break;
chunk.append(c);
marker++;
}
} else
{
while (marker < slength)
{
c = s.charAt(marker);
if (isDigit(c))
break;
chunk.append(c);
marker++;
}
}
return chunk.toString();
}
public int compare(String s1, String s2)
{
int thisMarker = 0;
int thatMarker = 0;
int s1Length = s1.length();
int s2Length = s2.length();
while (thisMarker < s1Length && thatMarker < s2Length)
{
String thisChunk = getChunk(s1, s1Length, thisMarker);
thisMarker += thisChunk.length();
String thatChunk = getChunk(s2, s2Length, thatMarker);
thatMarker += thatChunk.length();
// If both chunks contain numeric characters, sort them numerically
int result = 0;
if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0)))
{
// Simple chunk comparison by length.
int thisChunkLength = thisChunk.length();
result = thisChunkLength - thatChunk.length();
// If equal, the first different number counts
if (result == 0)
{
for (int i = 0; i < thisChunkLength; i++)
{
result = thisChunk.charAt(i) - thatChunk.charAt(i);
if (result != 0)
{
return result;
}
}
}
} else
{
result = comparator.compare(thisChunk, thatChunk);
}
if (result != 0)
return result;
}
return s1Length - s2Length;
}
private static class NaturalComparator implements Comparator<String> {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
}
}
0 votes
Amusant, tout le monde - relisez la question et supprimez les réponses postées ! !! .. :) Je suppose que c'est le pouvoir du DOWNVOTE ! !! :) ;)
2 votes
BTW. Le numérique n'est pas l'ordre naturel lorsqu'on parle de chaînes de caractères, la question est donc un peu trompeuse.
2 votes
Rien de tel intégré à ma connaissance. Quand coder prend moins de temps que de demander sur SO, je cours généralement pour ma propre roue... :)
4 votes
@Oscar généralement, l'ordre de tri naturel signifie que "image10.jpg" est trié plus grand que "image9.jpg". en d'autres termes, les parties numériques de la chaîne sont traitées comme des entiers et comparées comme telles. mon exemple n'est pas différent, sauf qu'il est "plus proche" d'une valeur purement numérique. mais le même algorithme traiterait les deux aussi bien.
9 votes
Rien n'est naturel en ce qui concerne la comparaison des versions. La 1.2.10p1 est-elle avant ou après la 1.2.10 ? Qu'en est-il de 1.2.10b1, et 1.20.10pre1 ?
0 votes
@subtenante- je suis d'accord, mais je suis à quelques heures de codage d'avoir besoin de faire le tri, alors je me suis dit que je laisserais SO travailler pour moi pendant que je travaille sur d'autres choses. :)
0 votes
Martin
1.2.10 < 1.2.10b1 < 1.2.10p1 < 1.20.10pre1
. je suppose que cela peut varier pour certains ateliers de développement, mais pour moi, ces cordes auraient pu être tout aussi bienalbum1page2image10.jpg < album1page2image10b1.jpg < album1page2image10p1.jpg < album1page20image10pre1
l'algorithme serait le même dans les deux cas.0 votes
@Kip, je suis d'accord, je voulais dire que le sens "naturel" de java diffère. J'ai posté une réponse avec les résultats, faites-nous savoir si cela vous aide.
0 votes
@Oscar @martin J'ai mis à jour la question pour être plus explicite sur ce que je voulais dire.