Reputation: 55
I need to conduct a comparison of values within a List of the following type;
List<org.bson.Document>
The data is a Bson Document with two key:value pairs (name and score). I need to iterate through this List and remove the lowest of the scores each golfer has made. So, if Joe has played two games and the first game he scored 72 and the second game he scored 86, because this is golf and 86 is the lower of the two scores, I need to remove the element from the List that has the score 86. This will then leave just the higher of the two for each golfer and allow me to then compare only the high scores (lower numerical value).
What is the best way to do this using any newer capabilities of Java 1.8 or, am I going to have to duplicate the list and then compare element x in List A to element x+1 in List B (after proper sorting) while names are equal?
Upvotes: 1
Views: 1455
Reputation: 7008
I am not familiar with bson so my attempt at getting a stream of name,score entries is this:
List<org.bson.Document> ldoc = new ArrayList<>();
Stream<Entry<String, Integer>> s
= ldoc.stream()
.flatMap(d -> d.entrySet().stream())
.map(e -> new AbstractMap.SimpleImmutableEntry<String,Integer>(e.getKey(),((Integer)e.getValue())));
I created the Stream directly from a list.
List<Entry<String, Integer>> l = new ArrayList<>();
l.add(new AbstractMap.SimpleImmutableEntry<>("Joe", 72));
l.add(new AbstractMap.SimpleImmutableEntry<>("Joe", 66));
l.add(new AbstractMap.SimpleImmutableEntry<>("John", 73));
l.add(new AbstractMap.SimpleImmutableEntry<>("John", 86));
l.add(new AbstractMap.SimpleImmutableEntry<>("John", 99));
One can group and minimize in the same stream like this:
Map<String, Optional<Integer>> m = l.stream()
.collect(Collectors.groupingBy(e -> e.getKey(),
Collectors.mapping(e -> e.getValue(),
Collectors.minBy((i1, i2) -> Integer.compare(i1, i2)))));
System.out.println("m = " + m);
This produce the output:
m = {Joe=Optional[66], John=Optional[73]}
That is this is a map of each players lowest score by name.
To get the winner:
String winner = m.entrySet()
.stream()
.min((e1, e2) -> Integer.compare(e1.getValue().get(), e2.getValue().get()))
.get().getKey();
System.out.println("winner = " + winner);
Which prints:
winner = Joe
Upvotes: 1
Reputation: 1
If you know a way to iterate through the entire document for scores, you can sort the list in ascending order. After sorting, you can remove the last element from the list. There are a number of ways to sort lists. Some of the major ones are Bubble sort and selection sort.
You can also look for the index of the maximum value and remove that element. This method is much easier and much more efficient. I'll also give you a pseudo code for this method. In the code, list the name of Array list assigned by you.
int max = list.get(0);
index = 0;
for(int i = 1; i < list.size(); i++)
{
if(list.get(i) > max)
{
max = list.get(i);
index = i;
}
}
list.remove(i);
Upvotes: 0
Reputation: 71
I am not sure with your question. But What I understood from the description, I would recommend you to use HasMap>.
In that way you will be able to sort value for each player and can easily remove the lowest score!!
Upvotes: 0
Reputation: 165
I am not really in the know about 1.8, but i would simply compare the entries in the same list, without creating a second one. I would do it like this (with pseudo-methods, i don't know bson):
for (int i=0; i<List.length;i++) {
int bestScore = List.getElementAt(i).getScore();
int bestLocation = i;
String currname = List.getElementAt(i).getName();
for (int j=i+1;i<List.length;j++) {
if (List.getElementAt(j).getName().equals(currname)) {
if (List.getElementAt(j).getScore()<bestScore) {
List.removeElementAt(bestLocation);
bestScore = List.getElementAt(j).getScore();
bestLocation = j;
} else {
List.removeElementAt(j);
j--;
}
}
}
}
... or sortof. Think you get my idea. You might need to look out for some errors this might cause, but i hope i could help you with this idea.
Also since List.length changes this propably wouldn't work, but that could be added to the code when it deletes something.
Upvotes: 0
Reputation: 625
Do you have to use List? Try using a hashMap, that way you can check if the player you are trying to insert in the hashMap already exist, and if so, you look his score, if it is worse, you overwrite it. After that, you should get hashMap of players with their highest score.
EDIT: My bad.. I haven't read your question properly. You have to use bson.Document data type. In that case you can use treeSet and define a custom comparator, that will return 0 (true) if the two elements (players) havethe same name. Then you can apply the same logis as writen in the original answer.
Upvotes: 0