Sorting Scores Java - java

I have a few methods that I was given from here a few days ago to help me with my scores. Basically when the game ends I want to get the top players with the best scores and put them into round 2, so if there were 8 players I want it to split them in half and the top half being the ones with the best scores, the methods below work fine but if there were 3 players in the game it would only take the top one instead of 2, 5 players in the game it would only take the top 2 instead of 3.
How do I get the top half with the highest scores and if say 2 players have the same score, then both of them would go through. For example:
Player 1 = 1;
Player 2 = 10;
Player 3 = 10;
Player 4 = 25;
Methods below would return player 4 and 3 but player 2 also has 10 points so he should be in it too.
public static Map<String, Integer> getTopHalf(Map<String, Integer> map){
Map<String, Integer> sorted = sortByComparator(map);
Map<String, Integer> out = new HashMap<String, Integer>();
Iterator<Entry<String,Integer>> it = sorted.entrySet().iterator();
for(int i = 0; i<map.size()/2; i++){
Entry<String, Integer> e = it.next();
out.put(e.getKey(), e.getValue());
}
return out;
}
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap){
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>(){
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2){
return o2.getValue().compareTo(o1.getValue());
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list){
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
public static void printMap(Map<String, Integer> map){
for (Entry<String, Integer> entry : map.entrySet()){
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
And for testing I use this:
Map<String, Integer> unsortMap = new HashMap<String, Integer>();
unsortMap.put("B", 89);
unsortMap.put("A", 45);
unsortMap.put("f", 43);
unsortMap.put("j", 47);
unsortMap.put("h", 41);
System.out.println("After sorting descindeng order and deleting half......");
Map<String, Integer> half = getTopHalf(unsortMap);
printMap(half);

List<Integer> achievedPoints = new ArrayList<>(allPlayers.values());
Collections.sort(achievedPoints); /*- from few points to many points */
int requiredScore = achievedPoints.get(achievedPoints.size());
Map<String, Integer> playersInNextRound = new HashMap<>();
for (Map.Entry<String, Integer> player : allPlayers.entrySet()) {
if (player.getValue() >= requiredScore) {
playersInNextRound.put(player.getKey(), player.getValue());
}
}

Related

Leaderboard displaying entire list instead of pagination

I have a list of users (stored in a properties file) that have a level. I sort the users by their level and then send the sorted list back to the guild. I paginate the list, but its still showing all of the users instead of just 10 per page.
Map<String, Integer> unsortedMap = new HashMap<String, Integer>();
for (String key : prop.stringPropertyNames()) {
String value = prop.getProperty(key);
unsortedMap.put(key, Integer.valueOf(value));
}
Map<String, Integer> sortedMap = sortByValue(unsortedMap);
EmbedBuilder eb = new EmbedBuilder();
eb.setTitle("aaaaaaaaaaaa");
ArrayList<Page> pages = new ArrayList<>();
for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
String key = entry.getKey();
int value = entry.getValue();
if (key.contains(".level")) {
User users = ctx.getJDA().retrieveUserById(key.replace(".level", ""), true).complete();
eb.addField(users.getName(), String.valueOf(value), false);
}
}
for (int i = 0; i < sortedMap.size(); i++){
pages.add(new InteractPage(eb.build()));
}
channel.sendMessageEmbeds((MessageEmbed) pages.get(0).getContent()).queue(success -> {
Pages.paginate(success, pages, true);
});
}
private static Map<String, Integer> sortByValue(Map<String, Integer> unsortedMap) {
List<Map.Entry<String, Integer>> list = new LinkedList<Map.Entry<String, Integer>>(unsortedMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return (o2.getValue().compareTo(o1.getValue()));
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Map.Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
Partition the for loop into smaller parts using the for loop. Initialize the int outside of the loop and then increment the int for every entry and then divide the int by how many items you want displayed on the list. Ex:
int i = 0;
for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
i++;
if (i % 6 == 0) {
//add page here

Using Hashmaps to compare keys and values and add together values based on similar keys

So i was wondering how and if it was possible using Hashmaps, one containing only strings and the other containing a similar string key but a float value, to compare them and then from that comparison print out the amount of similar values in the first hashmap, and then the float from the second hashmap added together when their keys/values line up. Example below that should clarify what i mean and to do this dynamically.
CODE
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", (float) 19.95);
h2map.put("order2", (float) 19.95);
h2map.put("order3", (float) 39.9);
Set <String> singles = new HashSet<>(h2map.values());
if(h2map.keySet().equals(hmap.keySet())) {
// below prints out the states and amount of the states but how can i get the float values from hmap to be added together for the similar states and printed with their respective state?
for(String element : singles) {
System.out.println(element + ": " + Collections.frequency(hmap.values(), element));
}
}
Current Output
pending: 2
cancelled: 1
Desired Output
pending: 2 $59.85
cancelled 1 $19.95
Is this what you want?
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, Float> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", 19.95f);
h2map.put("order2", 19.95f);
h2map.put("order3", 39.9f);
Map<String, DoubleSummaryStatistics> grouping = hmap
.entrySet()
.stream()
.collect(Collectors.groupingBy(Map.Entry::getValue, Collectors.summarizingDouble(e -> h2map.get(e.getKey()))));
grouping.forEach((key, value) -> System.out.println(key + ": " + value.getCount() + " " + value.getSum()));
}
Note that there is no summarizing statistics collector for BigDecimal and this code works only with Float or Double. But for money calculations better use BigDecimal. It's possible to implement the custom collector if needed )
I have replaced the use of Float with BigDecimal for better accuracy. Also I used two maps, one for holding the summed value and the other for count:
public static void main(String[] args) {
HashMap<String, String> hmap = new HashMap<>();
HashMap<String, BigDecimal> h2map = new HashMap<>();
hmap.put("order1", "pending");
hmap.put("order2", "cancelled");
hmap.put("order3", "pending");
h2map.put("order1", new BigDecimal("19.95"));
h2map.put("order2", new BigDecimal("19.95"));
h2map.put("order3", new BigDecimal("39.9"));
//Map for holding sum
HashMap<String, BigDecimal> sum = new HashMap<>();
for(String key : h2map.keySet()){
if(hmap.get(key) != null){
String value = hmap.get(key);
if(sum.get(value) == null){
sum.put(value, h2map.get(key));
}else{
sum.put(value, (sum.get(value).add(h2map.get(key))));
}
}
}
//Map for holding count
HashMap<String, BigDecimal> countMap = new HashMap<>();
for(Iterator<Map.Entry<String, BigDecimal>> itr = sum.entrySet().iterator(); itr.hasNext(); ){
Map.Entry<String, BigDecimal> entry = itr.next();
String key = entry.getKey();
int count = Collections.frequency(hmap.values(), key);
countMap.put((key + count), sum.get(key));
itr.remove();
}
//For GC
sum = null;
countMap.forEach((k, v) -> System.out.println(k + " " + v));
}

Determine frequency of duplicate values from two Hashmaps

I have created 2 HashMaps that store string values from two txt files. I am able to successfully print which values are duplicated amongst both Maps, however, I am having trouble determining how many times each values are duplicated.
Here is my code to identify duplicate values:
// find if hashmaps contain duplicate values
boolean val = wordsMap.keySet().containsAll(wordsMap1.keySet());
// create new entry for hashmap
for (Entry<String, Integer> str : wordsMap.entrySet()) {
System.out.println("================= " + str.getKey());
if(wordsMap1.containsKey(str.getKey())){
System.out.println("Map2 Contains Map 1 Key");
}
}
System.out.println("================= " + val);
Any suggestions? Thank you
I am thinking of something along the lines of
Map.values().equals(Map1.values()){
count++;
}
If I understand correctly, you want to find values which are common to two map objects. (Add null and/or other checks as required)
public static int duplicateCount(Map<String, Integer> m1, Map<String, Integer> m2) {
int count = 0;
Collection<Integer> m1Values = m1.values();
Collection<Integer> m2Values = m2.values();
for (Integer i : m1Values) {
if (m2Values.contains(i)) {
count++;
}
}
return count;
}
Here's a sample program have written based on my understanding of your doubt. It finds and displays the duplicate keys and also the duplicate values along with their frequencies of repetition. The logic is: To find the frequency, pass the duplicate element from map1 and the map2 as a parameter to countFrequency() method, which in turn will return the count of repetition.
package com.rahul.stackoverflow;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class DuplicateValHashMap {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<String, Integer>();
Map<String, Integer> map2 = new HashMap<String, Integer>();
map1.put("A", 1);
map1.put("B", 2);
map1.put("C", 3);
map1.put("D", 4);
map1.put("E", 5);
map2.put("A", 1);
map2.put("F", 2);
map2.put("G", 1);
map2.put("H", 3);
map2.put("B", 2);
for(Entry<String, Integer> entrySet : map1.entrySet()){
if(map2.containsKey(entrySet.getKey())){
System.out.println("Map2 contains keys of map1.");
System.out.println("Duplicate keys are : " + entrySet.getKey());
}
if(map2.containsValue(entrySet.getValue())){
System.out.println("Map2 contains values of map1.");
System.out.println("Duplicate values are : " + entrySet.getValue()+
" which is repeated " + countFrequency(map2, entrySet.getValue())+ " times.");
}
}
}
public static int countFrequency(Map<String, Integer> map, Integer value){
int count = 0;
for(Entry<String, Integer> entrySet : map.entrySet()){
if(value == entrySet.getValue()){
count++;
}
}
return count;
}
}
To get the number of duplicate keys between Maps,
public static int getDuplicateKeyCount(Map<?, ?> m1, Map<?, ?> m2) {
Set<?> tempSet = new HashSet<>(m1.keySet());
tempSet.retainAll(new ArrayList<>(m2.keySet()));
return tempSet.size();
}
To get the number of duplicate values between Maps,
public static int getDuplicateValueCount(Map<?, ?> m1, Map<?, ?> m2) {
List<?> tempList = new ArrayList<>(m1.values());
tempList.retainAll(m2.values());
return tempList.size();
}
To get a Map containing the frequency of the values of m1 in m2
public static <K, V> Map<V, Integer> getValueFrequencyMap(Map<K, V> m1, Map<K, V> m2) {
Map<V, Integer> freq = new HashMap<>();
Collection<V> col = m2.values();
for(V val : m1.values()) {
freq.put(val, Collections.frequency(col, val));
}
return freq;
}

Sorting based on all heighest number

I want to get the person having highest values from all the tables. Below is the example which i retrieve from db
Id play(count) listen(count) display(count) comment(count)
a 3 1 4 2
b 2 5 3 7
c 6 3 0 1
d 0 0 5 4
e 6 4 8 9
f 4 2 5 7
in this all counts related to same id but coming from different tables.Here I want e(6,4,8,9) as sorting output. How can i do this sorting?
Try something like this:
Map<String, List<Integer>> map = new LinkedHashMap<>();
// Assuming that you are working with query output resultset
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
List<Integer> li = new ArrayList<>();
li.add(rs.getInt("PLAY"));
li.add(rs.getInt("LISTEN"));
li.add(rs.getInt("DISPLAY"));
li.add(rs.getInt("COMMENT"));
map.put(rs.getString("ID"), li);
}
} catch (SQLException e ) {
/* SQLException handler */
} finally {
if (stmt != null) { stmt.close(); }
}
map = sortByValues(map);
for (Map.Entry<String, List<Integer>> entry: map.entrySet()) {
System.out.println(entry.getKey() + "," + entry.getValue());
}
}
public static Map<String, List<Integer>> sortByValues(Map<String, List<Integer>> map) {
List<Map.Entry<String, List<Integer>>> list =
new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String, List<Integer>>>() {
public int compare(Map.Entry<String, List<Integer>> m1, Map.Entry<String, List<Integer>> m2) {
int sum1 = 0;
for(Integer d : m1.getValue())
sum1 += d;
int sum2 = 0;
for(Integer d : m2.getValue())
sum2 += d;
return (new Integer(sum2)).compareTo(new Integer(sum1));
}
}) ;
Map<String, List<Integer>> result = new LinkedHashMap<>();
for (Map.Entry<String, List<Integer>> entry: list) {
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Note: I have a separate method sortByValues() to do the comparison. This makes code neat to read and reusable rather than implementing an anonymous block after try-catch.
What's happening here?
Our aim is to sort IDs by different values fetched from Database. I feel Map data structure to be the apt one here. Example Map which is represented in a generic way as Map<String, List<Integers>>.
Map<String, List<Integer>> map = new LinkedHashMap<>();
Creates the linked hash map to store the pair
List<Integer> li = new ArrayList<>();
Creates an Arraylist object inside while loop to store each value fetched from database. It's scope dies within this loop.
map.put(id, li);
Adds each users id and values in the format Map<String, List<Integer>>
map = sortByValues(map);
Accesses the static sortByValues() to fetch the sorted map based on values it has.
sortByValues(Map<String, List<Integer>> map)
Overrides the Comparator's compare() anonymously and performs sorting based upon values. It sums up each ID's value and does the comparison.
Mock Execution:
Map<String, List<Integer>> map = new LinkedHashMap<>();
// Map<String, List<Integer>> map = new HashMap<>();
List<Integer> li = new ArrayList<>();
li.add(1);
li.add(2);
li.add(3);
// MathUtils.sum()
map.put("a", li);
// map.put("a", 5);
List<Integer> li2 = new ArrayList<>();
li2.add(3);
li2.add(-1);
li2.add(1);
map.put("b", li2);
List<Integer> li3 = new ArrayList<>();
li3.add(10);
li3.add(-1);
li3.add(9);
map.put("c", li3);
map = sortByValues(map);
for (Map.Entry<String, List<Integer>> entry: map.entrySet()) {
System.out.println(entry.getKey() + "," + entry.getValue());
}
Result:
c,[10, -1, 9]
a,[1, 2, 3]
b,[3, -1, 1]

Sorting by values in HashMap class using Java

I'm trying to get results HashMap sorted by value.
This is HashMap's keys and values:
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
I try to get results like this:
1 = can
2 = selin
4 = burak
5 = ertu
Here is my code:
import java.util.*;
public class mapTers {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext()) {
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++) {
while (t.hasNext()) {
if (dizi[i].equals(map.get(t.next()))) {
System.out.println(dizi[i] + " = " + t.next());
}
}
}
}
}
You can sort the entries as follows (but note this won't sort the map itself, and also HashMap cannot be sorted) -
List<Map.Entry<String, Integer>> entryList = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entryList, new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
Every time that you call t.next(), the iterator's pointer is moved forward. Eventually, the iterator reaches the end. You need to reset the iterator. Also, calling t.next() twice moves the pointer twice.
Here's my solution:
import java.util.*;
public class mapTers
{
public static void main(String[] args)
{
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("ertu", 5);
map.put("burak", 4);
map.put("selin", 2);
map.put("can", 1);
Integer dizi[] = new Integer[map.size()];
Set anahtarlar = map.keySet();
Iterator t = anahtarlar.iterator();
int a = 0;
while (t.hasNext())
{
dizi[a] = map.get(t.next());
a++;
}
Arrays.sort(dizi);
for (int i = 0; i < map.size(); i++)
{
t = anahtarlar.iterator();
while (t.hasNext())
{
String temp = (String)t.next();
if (dizi[i].equals(map.get(temp)))
{
System.out.println(dizi[i] + " = " + temp);
}
}
}
}
}
You cannot do that from a Map. At least not directly.
Retrieve the keys/entries, get all the map data in a more suitable structure (hint: a class that encapsulates both attributes and is is stored in a sortable (hint2: SortedSet, List)) and sort.
Do not forget to extend Comparable (and implement compareTo) or, otherwise, create a Comparator.
This is one of the solutions take from: https://stackoverflow.com/a/13913206/1256583
Just pass in the unsorted map, and you'll get the sorted one.
private static Map<String, Integer> sortByComparator(Map<String, Integer> unsortMap, final boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(unsortMap.entrySet());
// Sorting the list based on values
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getValue().compareTo(o2.getValue());
}
else {
return o2.getValue().compareTo(o1.getValue());
}
}
});
// Maintaining insertion order with the help of LinkedList
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
To print, do a simple iteration over the entry set:
public static void printMap(Map<String, Integer> map) {
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "+ entry.getValue());
}
}
You probably have the wrong data structure for this problem. Either:
Reverse the map so the integers are the keys and the words the values and make the map a SortedMap, or
Use a bidirectional map as provided by libraries like Google Guava.
Reversed Map
private final SortedMap<Integer, String> TRANSLATIONS;
static {
SortedMap<Integer, String> map = new TreeMap<>();
map.put(1, "can");
// ...
TRANSLATIONS = Collections.unmodifiableSortedMap(map);
}
Guava BiMap
private final BiMap TRANSLATIONS =
new ImmutableBiMap.Builder<String, Integer>()
.put("ertu", 5);
.put("burak", 4);
.put("selin", 2);
.put("can", 1);
.build();
Then, iterate over a sorted version of the key set or value set as needed. For example,
TRANSLATIONS.inverse.get(4); // "burak"
I'm just curious. What language are your strings in?

Categories

Resources