I have this code. I want to order a list of strings. Every item in the list consists of a three word sentence. I want to ignore the first word and sort the sentence lexicographically with the 2nd and 3rd words. If the 2nd or 3rd words contain an integer, I want to ignore sorting them but add them to the end of the list. For example: (19th apple orange, 17th admin 7th, 19th apple table) should be sorted in the list as (19th apple orange, 19th apple table, 17th admin 7th) So far my code only ignores the first word and sort lexicographically the rest of the lists
public static List<String> sortOrders(List<String> orderList) {
// Write your code here
Collections.sort( orderList,
(a, b) -> a.split(" *", 2)[1].compareTo( b.split(" *", 2)[1] )
);
return orderList;
}
CodePudding user response:
In your compare method check for numbers first and then strings. You just have to add code to the steps you described:
Here's a pseudo code of what you described
...
(a,b) -> {
// Every item in the list consists of a three word sentence.
var awords = a.split(" ")
var bwords = a.split(" ")
// I want to ignore the first word
var as = awords[1] " " awords[2]
var bs ...
// and sort the sentence lexicographically with the 2nd and 3rd words.
var r = as.compareTo(bs)
// If the 2nd or 3rd words contain an integer, I want to ignore sorting them but add them to the end of the list
if ( as.matches(".*\\d.*) ) {
return -1
} else {
return r
}
}
...
It's not clear what to do if both have numbers, e.g. a 1 a
vs a 1 b
, but that's something you have to clarify.
So basically you just have to go, divide each of the statements in your problem and add some code that solves it (like the example below )
You might notice there are some gaps (like what to do if two of them have strings). Once you have a working solution you can clean it up.
Another alternative with a similar idea
var as = a.substring(a.indexOf(" ")) // "a b c" -> "b c"
var bs = b.substring(b.indexOf(" ")) // "a b c" -> "b c"
return as.matches("\\d ") ? -1 : as.compareTo(bs);
Remember the compare(T,T)
method returns < 0 if a is "lower" than b, so if a
has numbers, it will always be "higher" thus should return 1
, if b
has numbers then a
will be "lower", thus it should return -1
, otherwise just compare the strings
Here's the full program:
import java.util.*;
public class Sl {
public static void main(String ... args ) {
var list = Arrays.asList("19th apple orange", "17th admin 7th", "19th apple table");
Collections.sort(list, (a, b) -> {
// just use the last two words
var as = a.substring(a.indexOf(" "));
var bs = b.substring(b.indexOf(" "));
// if a has a number, will always be higher
return as.matches(".*\\d .*") ? 1
// if b has a number, a will always be lower
: bs.matches(".*\\d .*") ? -1
// if none of the above, compare lexicographically the strings
: as.compareTo(bs);
});
System.out.println(list);
}
}
CodePudding user response:
Try this.
public static List<String> sortOrders(List<String> orderList) {
return orderList.stream()
.map(str -> new Object() {
String org = str;
String key;
{
key = str.replaceFirst("^.* ", "");
if (key.matches(".*\\d.*"))
key = "\uffff";
}})
.sorted(Comparator.comparing(obj -> obj.key))
.map(obj -> obj.org)
.toList();
}
And
List<String> list = Arrays.asList(
"19th apple orange",
"17th admin 7th",
"19th apple table");
System.out.println(sortOrders(list));
output:
[19th apple orange, 19th apple table, 17th admin 7th]