Sort integers having special character in Java - java

I have a problem where I need to sort Integers separated by hyphen either in ascending or descending order.
I tried using
Collections.sort(list, Collections.reverseOrder());
Where list is an instance of ArrayList created, but its not giving me the exact result.
The arrayList looks like this:
[91,95,96-1,94-2,94-1,100-2].
The expected way is:
[91,94-1,94-2,95,96-1,100-2]

Using the default sorting on Strings will use a lexicographical order, whereas you intend to sort the Strings in a numerical order (and if the first number is equal, by the second number). A way to accomplish this is by using two Comparators:
List<String> list = new ArrayList<>(Arrays.asList("96-1","91","94-2","100-2","94-1","95"));
System.out.println("Unsorted: "+list);
Comparator<String> primaryComparator =
(a,b)->Integer.valueOf(a.split("-")[0])
.compareTo(Integer.valueOf(b.split("-")[0]));
Comparator<String> secondaryComparator =
(a,b)->Integer.valueOf(a.split("-")[1])
.compareTo(Integer.valueOf(b.split("-")[1]));
list.sort(primaryComparator.thenComparing(secondaryComparator));
System.out.println("Sorted: "+list);
list.sort(primaryComparator.thenComparing(secondaryComparator).reversed());
System.out.println("Sorted in reverse: "+list);
Try it online.
As for the comparators themselves, I assumed the Strings in the list are always valid, and always of the form \d+(-\d+)?, so either an integer, or two integers separated with a hyphen. (If this is not the case, you might want to add some additional checks/validations with a custom Java 7 style comparator to make it more readable then the Java 8 style lambdas.)
The .split("-")[0] / .split("-")[1] will split this String on the hyphen, and takes either the first or last integer depending on the comparator. It will then convert this to an integer with Integer.valueOf(...), and will use the default integer comparing builtin Integer1.compareTo(Integer2).

Related

How to sort an array of Strings that contain "m" first, everything else second

String[] strArray = {"xyz", "aaazzz","abc","mft","gh","j", "aaazaz", "mm", "am"};
Arrays.sort(strArray, Comparator.comparing((s) -> s.contains("m")));
System.out.println("Array sorted by 'm': " + Arrays.toString(strArray));
I have been able to get the array so that it is sorted using 'm', but the results are in defending order - as in all strings that contain 'm' are at the end.
My print out reads;
Array sorted by 'm': [xyz, aaazzz, abc, gh, j, aaazaz, mft, mm, am]
I have considered using indexOf() but I haven't been able to figure out a way to get this to work.
Many thanks for any suggestions!
The natural order of boolean values is false -> true (i.e. false comes first).
You need to change the condition of your Comparator to get elements containing m to be placed and the beginning of the sorted list:
Comparator.comparing(s -> !s.contains("m"))
You might want both groups of string (with and without m) to be sorted as well. For that you can use method thenComparing() which allow to build an aggregate Comparator based on several conditions:
Comparator.comparing((String s) -> !s.contains("m"))
.thenComparing(Comparator.naturalOrder());
Note that when comparators are being chained together, the type inference mechanism fails to infer the types of arguments used in the chained methods based on the target type (i.e. the expected aggregate Comparator). And we need to either provide the types of argument in the lambda expression explicitly, like shown above (String s) -> ..., or use a so-called type-witness <String, Boolean>comparing(...).

Java stream sorting a List of String as numbers problem

I have an issue sorting a list of QuestionNumbers as Strings.
List<String> list = Arrays.asList("12.2", "12.1", "12.3", "12.4", "12.5", "12.10");
List<String> sortedList = list.stream().sorted().collect(Collectors.toList());
When printed out sortedList I get:
12.1
12.10
12.2
12.3
12.4
12.5
I tried the following but getting a multi points errors. Please help
.sorted(Comparator.comparingDouble(question ->(Double.parseDouble(question.getQuestionNumber())) ))
String.compareTo compares Strings lexicographically. Digits are just characters in such a comparison, no different from letters or punctuation or emojis.
You need a Comparator which recognizes the nn.nn format. You could write a new Comparator, but a more manageable approach is to have a class which parses such strings.
If you’re using Java 9 or later, you’re in luck: There’s already such a class. That class is Runtime.Version.
So you can sort your strings by comparing their respective Runtime.Version equivalents, then converting the sorted objects back to strings:
List<String> sortedList =
list.stream().map(Runtime.Version::parse).sorted()
.map(Object::toString).collect(Collectors.toList());
As it was written in comments: you can combine two Comparator first is by length, then by String value.
list.stream()
.sorted(Comparator
.comparing(String::length)
.thenComparing(String::compareTo))
.collect(Collectors.toList());
UPDATE
As it was written by Holger there are some problems with above approach.
It can be rewrite as below:
list.stream()
.sorted(Comparator.comparing((String s) -> s.split("\\."),
Comparator
.comparing((String[] a) -> Integer.parseInt(a[0]))
.thenComparingInt((a) -> a.length > 1 ? Integer.parseInt(a[1]) : 0))
)
.collect(Collectors.toList());
But it looks more complicated and it's doing more or less the same what was proposed by VGR. So in the end you can write it like this:
list.stream()
.sorted(Comparator.comparing(Runtime.Version::parse))
.collect(Collectors.toList());
You're sorting string, your result is correct if you want to sort a string. But in your case, you should convert it to float, double, Double or BigDecimal...
Try this code:
List list = Arrays.asList("12.2", "12.1", "12.3", "12.4", "12.5", "12.10");
List sortedList = list.stream()**.map(Double::valueOf)**.sorted().collect(Collectors.toList());
Converting this value, you will have the correct order for numbers.

Array out of order after sort in Java

I have a Java String array containing the values 1-10. When I run Arrays.sort() on it however, it becomes 1, 10, 2, 3, 4...9. Does anyone know why the 10 is out of order? Is it because its a string array instead of an int array? Any help appreciated!
Yes, this happens because it's array of Strings.
Default sorting for String type - simple Unicode ordering is similar to alphabetical sorting. That's why your result looks like that.
If you change type to int, everything should be fine.
Array.sort()'s sorting algorithm is set by its content's natural ordering (the content's implementation of the Comparable interface).
You can check a class' sort by going to the Java documentation and checking the class' implementation. For example, String's implementation (under String.compareTo(String)) specifies that this is done by lexicographical order (more commonly known as alphabetical order).
In order to fix this issue, add leading 0's to your other numbers, or use a different content type (like int).

Lexicographic sorting in java?

I am trying to sort 3 strings alphabetically using the compareTo method in java without using arrays.
Is the fastest way to do this by setting up 6 compare statements and sorting by least to greatest or is there any easier way? Thanks!
put it into TreeSet.
TreeSet<String> t = new TreeSet<>();
t.add("stack");
t.add("over");
t.add("flow");
System.out.println(t);
OutPut:
[flow, over, stack]

Comparing any of these value from an array Efficiently

I am having an Array of String of 10 elements.
Now I need to compare my value available in any of these Arrays value.
1 Option I thought of sorting the array and then binary search on the
same
But further analysis, I found the value needed to be compare is not exactly same, it contains some value , but even in that case, it should be successful.
Like Value to compare ,
String str = "Author"
String[] arrays = {"#Author","#Auth",#Au...}
str.contains(arrays..) actually but how to do the same .
you could use Dynamic Programming:
http://www.algorithmist.com/index.php/Longest_Common_Subsequence
this algorithm check the longest subsequence of string with the minimum complex
This is the algor in java:
http://introcs.cs.princeton.edu/java/96optimization/LCS.java.html
If you are only dealing with an array with only 10 elements... you don't need to worry about efficiency!
You can simply loop through the entire array, or instead of using a String[] use an List<string> and use the contains method.

Categories