I have IDs with the following format : XXXXXXYYY00000
What I am trying to do is to get a single string organised alphabetically by the 6 first characters (the 6 x's (they can be any character)) with each new ID separated by a new line character
For example :
AOPSIKPMI23495 would go before BWLMBEPMI00001
What I have so far is :
String = String + this.ID + "\n";
And I have no idea how to approach my problem in order to solve it.
My question is the following : How do I organise my IDs alphabetically, only by its first 6 characters (meaning if there's a tie with the 6 first characters, it still shouldn't resolve it with the next 3 characters) and still keeping my String ?
you can sort the list by the first 6 characters and then use Collectors.joining to separate each string with a "\n" delimiter.
String result = myList.stream().sorted(Comparator.comparing(e -> e.substring(0,6)))
.collect(Collectors.joining("\n"));
You can simply implement a comparator just to compare the first 6 characters:
class FirstSixCharComparator implements Comparator<String> {
#Override
public int compare(String a, String b) {
return a.substring(0,6)compareTo(b.substring(0,6));
}
}
Then use the comparator to perform a sort:
Collections.sort(list, new FirstSixCharComparator<String>()); //for collections
Arrays.sort(array, new FirstSixCharComparator<String>()); //for arrays
this piece of code should solve your problem , if its not then we can write comparator kind of stuff to satisfy whatever requirement you have of it.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Sample {
public static void main(String[] args) {
List<String> words = new ArrayList<String>();
words.add("AOPSIKDDD23495");
words.add("BWLMBEPMI00001");
Collections.sort(words);
System.out.println(words);
}
}
Related
Let's say I have this class below:
class Product{
String name;
...
}
And then I make a list of products, List<Product> products. Let's say that there are 3 object with names=("A-Product-12", "A-Product-2", "A-Product-1").
I tried several ways, but it's always results to this order=("A-Product-1", "A-Product-12", "A-Product-2"), but I want it to be in this order=("A-Product-1", "A-Product-2", "A-Product-12")
I've tried using products.sort(), Arrays.sort(), stream().sorted() and using several comparators including Comparator.naturalOrder (which works against numeric only, but not with complex alphanumeric)
You need to write your own custom Comparator that will compare only number from this String (or implement compareTo method in Product class). It can look like this:
List<String> strings = Arrays.asList("A-Product-12", "A-Product-2", "A-Product-1");
Collections.sort(strings, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
int n1 = Integer.parseInt(s1.split("-")[2]); // Get numeric part of first string
int n2 = Integer.parseInt(s2.split("-")[2]); // Get numeric part of second string
return Integer.compare(n1, n2); // Compare the numeric parts of the strings
}
});
System.out.println(strings); // Output: [A-Product-1, A-Product-2, A-Product-12]
Implementing the Comparable interface with the Product class allows us to sort Product objects directly.
public class Product implements Comparable<Product>
We then define how we want this class to be sorted by overriding the compareTo method. This is done in the Product class.
This is a clean way of implementing the sorting of products (a collection of Product objects). If we want to change the way they are sorted, we know exactly where to go to do this, and the changes will be implemented anywhere we have sorted Product objects. For example, let's say we want to add products starting with the letter B ("B-Product-3") and we want the products to be sorted first by this letter and then by the number at the end. We could do this with the following compareTo method in the Product class:
#Override
public int compareTo(Product product) {
int thisProductNumber = Integer.parseInt(name.split("-")[2]);
int compareToProductNumber = Integer.parseInt(product.name.split("-")[2]);
String thisBaseProductName = name.split("-")[0] + "-" + name.split("-")[1];
String compareToBaseProductName = product.name.split("-")[0] + "-" + product.name.split("-")[1];
return thisBaseProductName.compareTo(compareToBaseProductName) == 0 ?
thisProductNumber - compareToProductNumber : thisBaseProductName.compareTo(compareToBaseProductName);
}
Sorting is done with one line: Collections.sort(products);
If we have products with names=("A-Product-12", "A-Product-2", "B-Product-3", "A-Product-1")
Sorting them gives us ("A-Product-1", "A-Product-2", "A-Product-12", "B-Product-3")
Better to create a custom Comparator as #Pekinek mentioned.
Here's another version:
public class NumberComparator implements Comparator<Product> {
#Override
public int compare(Product p1, Product p2) {
String p1str = p1.getName().replaceAll("[^0-9]", "");
String p2str = p2.getName().replaceAll("[^0-9]", "");
int p1number = Integer.parseInt(p1str);
int p2number = Integer.parseInt(p2str);
return Integer.compare(p1number, p2number);
}
}
In main class you can do
Collections.sort(list,new NumberComparator());
The reason for your result is you were going to sort strings. when going to sort this string list, read left to right by getting each product name and ordered. when consider A-Product-12 and A-Product-2, In 'A-Product-12', it has '1' before the '2'. so that it give priority to 12 than 2 in 'A-Product-2'. If you want to get your expected result you can use your list with map or you can apply logic to sort using last characters those are petitioned after the last character '-'.
I just finished a coding competition where one of the problems required me to sort an array of strings, but numerically based on the number that appeared first in the string. for example:
String[] array =
{{"18.sdfahsdfkjadf"},
{"1.skjfhadksfhad"},
{"2.asldfalsdf"}};
would need to be sorted as 1.sk... first, 2.as..., and then 18.sd... last. But if you use (in Java) Arrays.sort(array), it would be ordered as 1, 18, then 2 because its going off the the first char first and not as a number.
You can split each string on \D (which means non-digit) and compare the strings based on the first elements, parsed into an integer, of the resulting arrays.
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws InterruptedException {
String[] array = { "18.sdfahsdfkjadf", "1.skjfhadksfhad", "2.asldfalsdf" };
Arrays.sort(array,
(s1, s2) ->
Integer.compare(
Integer.parseInt(s1.split("\\D")[0]),
Integer.parseInt(s2.split("\\D")[0])
)
);
System.out.println(Arrays.toString(array));
}
}
Output:
[1.skjfhadksfhad, 2.asldfalsdf, 18.sdfahsdfkjadf]
Using the Streams API, you could produce something like this (assuming the numbers are always separated from the rest by punctuation):
List<String> sorted = Arrays.stream(array).sorted((s1, s2) -> {
Integer i = Integer.parseInt(s1.split("\\.")[0]);
Integer j = Integer.parseInt(s2.split("\\.")[0]);
return i.compareTo(j);
}).collect(Collectors.toList());
With the resulting array being:
[1.skjfhadksfhad, 2.asldfalsdf, 18.sdfahsdfkjadf]
Try this.
Arrays.sort(array, Comparator.comparingInt(s -> Integer.parseInt(s.split("\\.")[0])));
System.out.println(Arrays.toString(array));
output:
[1.skjfhadksfhad, 2.asldfalsdf, 18.sdfahsdfkjadf]
Given a list of strings of different length, we need find out string that would come in first in dictionary among strings generated by combination of given strings.
For Input:
cda,bcs,fgr,cd
output should be bcscdcdefgr
Is there any better way than generating all the combinations of strings and comparing them? Please help.
It appears that you just want ascending dictionary order. If so, then a plain collections sort should work here:
List<String> words = Arrays.asList(new String[] { "cda", "bcs", "fgr", "cd" });
Collections.sort(words);
String output = String.join("", words);
System.out.println(output);
This prints:
bcscdcdafgr
You can try this approach. Sorting directly would fail as b would before ba.
List<String> words = Arrays.asList(new String[] {"b","ba","c"});
Collections.sort(words,new Comparator<String>(){
#Override
public int compare(String s1, String s2) {
return (s1+s2).compareTo(s2+s1);
}
});
String output = String.join("", words);
System.out.println(output);
You need a simple observation, as to why a simple sort wouldn't work. Sorting ["b", "bb", "bba"] in descending order will give you ["bba", "bb", "b"]. However, the word that would occur first in a dictionary would've been ["bb", "bba", "b"].
You need to create a comparator, where you can compare strings x and y as follows:
Create string a = x+y and string b = y+x (basically xy and yx)
Compare a and b. If a>b, that means x should be put first to achieve the correct dictionary order. Otherwise y should be put first.
A simple of doing that would be:
static void printLargest(Vector<String> arr)
{
Collections.sort(arr, new Comparator<String>()
{
#Override public int compare(String X, String Y)
{
String XY = X + Y;
String YX = Y + X;
return XY.compareTo(YX) > 0 ? -1 : 1;
}
});
}
This solution uses no extra space and has O(NlogN) time complexity.
Hello everyone I have a code using an arraylist, these are the test inputs to be added. But after I use the sort method. The output is not the one I expected.
ArrayList<String> test= new ArrayList<>();
test.add("2,2,17");
test.add("5,4,24 ");
test.add("8,1,11");
test.add("19,0,0");
test.add("2,3,21");
test.sort(null);
Output :
19,0,0
2,2,17
2,3,21
5,4,24
8,1,11
My desired out put should be :
2,2,17
2,3,21
5,4,24
8,1,11
19,0,0
Is there a way to sort "19,0,0" to be at the end, or any number to be add to make it the end of the arrayList?
You'll want to use Collections.sort, something like this:
Collections.sort(list, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
int s1int = Integer.parseInt(s1.substring(0, s1.indexOf(",")));
int s2int = Integer.parseInt(s2.substring(0, s2.indexOf(",")));
return s1int - s2int;
}
});
You can use Collections.sort()
https://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator).
And define a Comparator to compare the objects in the list.
In order for the strings to be sorted alphabetically rather than numerically, you will need to implement a comparator that converts the strings to integers for the comparison. You can then use this comparator with Collections.sort() to sort your list.
A better option would be to store your integers as integers in a 2D array rather than as strings (or some kind of nested list if the dimensions are not known up-front); however, I'd need to know more about how the data is created and used before uniformly proclaiming this to e the solution.
A possible flexible solution for Strings of various 'lengths', i.e. a different number of integers separated by commas.
Example list
2,2,17
5,4,24
19,0,2
8,1,11
19,0,1,2
19,0,1,4
2,3,21
2
Result after sorting
2
2,2,17
2,3,21
5,4,24
8,1,11
19,0,1,2
19,0,1,4
19,0,2
Code
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortExample {
public static void main(String[] args) {
List<String> test = new ArrayList<>();
test.add("2,2,17");
test.add("5,4,24");
test.add("19,0,2");
test.add("8,1,11");
test.add("19,0,1,2");
test.add("19,0,1,4");
test.add("2,3,21");
test.add("2");
Collections.sort(test, new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
String[] split1 = s1.split(",");
String[] split2 = s2.split(",");
final int indicesToCheck = Math.min(split1.length, split2.length);
int result = 0;
int i = 0;
while (result == 0 && i < indicesToCheck) {
result = Integer.compare(Integer.parseInt(split1[i]),
Integer.parseInt(split2[i]));
i++;
}
return result == 0 ? Integer.compare(split1.length, split2.length) : result;
}
});
for (String s : test) {
System.out.println(s);
}
}
}
This question already has answers here:
Sort ArrayList of custom Objects by property
(29 answers)
Closed 9 years ago.
Below is my list which will always be in the form of aXXXX -
List<String> child = Arrays.asList("a5", "a10", "a2", "a1", "a40");
System.out.println(child);
My child list will always have strings in the form of aXXXX
Now I need to sort my above lists and extract the largest string from it..
So in the above example, it will be a40. I was initially thinking to use Collections.sort(child); but it's not sorting them out in the ascending order properly.
You can use a Comparator which defines the sorting strategie:
See also http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
static final Comparator<String> aStringComparator = new Comparator<String>() {
public int compare(String s1, String s2) {
//assumed input are strings in the form axxxx
int numfromS1 = Integer.valueOf(s1.subSequence(1, s1.length()).toString());
int numfromS2 = Integer.valueOf(s2.subSequence(1, s2.length()).toString());
return numfromS1 - numfromS2;
}
};
public static void main(String[] args) {
List<String> child = Arrays.asList("a5", "a10", "a2", "a1", "a40");
Collections.sort(child, aStringComparator);
System.out.println(child);
}
}
Sorting will be possible, but you have to extract the "a" at the beginning and treat the rest as an integer number to prevent the string "2" from being bigger then the string "10". Try a Comparator doing this, or create a new list containing only extracted integers.
You was almost there. The possible solution is to write your own comparator:
Collections.sort(child,new Comparator<String>() {
#Override
public int compare(String lhs, String rhs) {
\\compare 2 values
return result;
}
});
http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
Possible values to return:
-1 : lhs < rhs
0 : lhs == rhs
+1 : lhs > rhs
Others have already shown how to do this with Java 7.
This could also be done with the following using Java 8:
List<String> child = Arrays.asList("a5", "a10", "a2", "a1", "a40");
String result = child.stream()
.sorted(
Collections.reverseOrder(
Comparator.comparing(
c -> Integer.parseInt(c.substring(1, c.length()))
)
)
)
.findFirst().get();
System.out.println(result);
What this does is:
Obtain a Stream<String> from your child.
Create a reversed Comparator<String>, which compares based on the lambda c -> Integer.parseInt(c.substring(1, c.length())), which parses the text from the second character onwards as a string.
Finds the first result.
Gets it out of the Optional<String> that findFirst() returns, with get().
The Comparator could be written more nicely by appending .reversed() to it instead of wrapping it in Collections.reverseOrder(), but I am unsure how it works as of now.