Reputation: 133
Java noob here. I want to sort an array of strings that contain periods / dots from smallest to largest.
So an array containing:
1.0.3
1.0.12
1.0.2
Is incorrectly being sorted like this:
1.0.12
1.0.2
1.0.3
When sorted correctly should be:
1.0.2
1.0.3
1.0.12
Here is the code I have so far, but it sorts it incorrectly.
public static String[] sort(String[] l) {
String[] ll=new String[l.length];
for(int i=0;i<l.length;i++)
{
}
for (int i = 0; i < l.length - 1; ++i) {
int minIndex = i;
for (int j = i + 1; j < l.length; ++j) {
if (l[j].compareTo(l[minIndex]) < 0) {
minIndex = j;
}
}
String temp = l[i];
l[i] = l[minIndex];
l[minIndex] = temp;
}
return l;
}
Upvotes: 3
Views: 1871
Reputation: 14853
EDIT Complete, runnable version.
Using a class, it may be simpler:
public class Version implements Comparable<Version> {
public final int major;
public final Integer minor;
public final Integer patch;
public Version( String ver ) {
final String[] parts = ver.split("\\.");
this.major = Integer.parseInt( parts[0] );
if( parts.length > 1 ) {
this.minor = Integer.parseInt( parts[1] );
if( parts.length > 2 ) {
this.patch = Integer.parseInt( parts[2] );
}
else {
this.patch = null;
}
}
else {
this.minor = null;
this.patch = null;
}
}
@Override
public int compareTo( Version right ) {
int diff = this.major - right.major;
if( diff != 0 ) {
return diff;
}
if( this.minor == null && right.minor == null ) {
return 0;
}
if( this.minor == null && right.minor != null ) {
return -1;
}
if( this.minor != null && right.minor == null ) {
return +1;
}
diff = this.minor - right.minor;
if( diff != 0 ) {
return diff;
}
if( this.patch == null && right.patch == null ) {
return 0;
}
if( this.patch == null && right.patch != null ) {
return -1;
}
if( this.patch != null && right.patch == null ) {
return +1;
}
diff = this.patch - right.patch;
return diff;
}
@Override
public String toString() {
return String.format( "%d.%d.%d", major, minor, patch );
}
public static void main( String[] args ) {
final List<Version> versions = new ArrayList<>( 20 );
versions.add( new Version( "5.3" ));
versions.add( new Version( "5.3.0" ));
versions.add( new Version( "2.5" ));
versions.add( new Version( "2.5.100" ));
final Random r = new Random( System.currentTimeMillis());
for( int i = 0; i < 20; ++i ) {
final int maj = r.nextInt( 10 );
final int min = r.nextInt( 10 );
final int pat = r.nextInt( 100 );
final Version v =
new Version( String.format( "%d.%d.%d", maj, min, pat ));
versions.add( v );
}
Collections.sort( versions );
versions.forEach( System.err::println );
}
}
Execution trace:
0.5.55
0.9.54
1.1.60
1.7.19
1.8.15
2.2.85
2.5.null
2.5.100
2.7.68
2.8.42
3.1.57
3.2.50
4.4.18
5.3.null
5.3.0
6.3.0
7.1.26
7.2.30
7.4.47
7.5.63
7.6.13
8.6.12
8.9.80
9.8.4
Upvotes: 3
Reputation: 56433
You can use streams to accomplish the task at hand. Instead of just comparing the strings as they're, you can split the strings on the delimiter .
then compare each digit against others; When we find that two digits are equal between two or more strings we then use .thenComparingInt
to further the comparison.
String[] array = {"1.0.3" ,"1.0.12", "1.0.2"};
String[] result = Arrays.stream(array)
.sorted(Comparator.comparingInt((String x) -> Integer.parseInt(x.split("\\.")[0]))
.thenComparingInt((String x) -> Integer.parseInt(x.split("\\.")[1]))
.thenComparingInt((String x) -> Integer.parseInt(x.split("\\.")[2]))).toArray(String[]::new);
the result array contains:
[1.0.2, 1.0.3, 1.0.12]
Upvotes: 0
Reputation: 1786
Maybe this dirty to parse and convert to numbers but it is solve our problem.
public void test() {
List<String> versions = new ArrayList<>(Arrays.asList(
"1.0",
"1.0.3",
"1.1.131",
"1.0.12",
"1.0.2"
));
List<String> expectedVersions = Arrays.asList(
"1.0",
"1.0.2",
"1.0.3",
"1.0.12",
"1.1.131"
);
Comparator<String> versionComparator = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return parsedVersion(o1) - parsedVersion(o2);
}
private int parsedVersion(String version) {
String cleared = version.replaceAll("\\.", "");
return Integer.parseInt(cleared);
}
};
versions.sort(versionComparator);
System.out.println(versions.equals(expectedVersions));
}
Upvotes: -1