2015-09-11 3 views
1

Я пытался хранить частоты строки в TreeMap, чтобы я мог получать наиболее часто используемые строки, скажем, определенного пользователя. Теперь я хочу написать метод, чтобы вернуть мне первые n элементов (наиболее часто используемых) из отсортированной карты.Получить первые n элементов из sortedmap

public TreeMap<String,Integer> getKeywords(int n){ 
    //Can check if sorted for efficiency! 

    println keywords.size(); 
    keywords=keywords.sort{a,b-> 
     //sort the map desc by value 
     b.value <=> a.value; 
    } 
    TreeMap<String,Integer> result=new TreeMap<>(); 
    //need to fill result with first n elements from keywords 
    return result; 
} 

Я попробовал несколько способов, как с помощью .each() по ключевым словам или перебирать его Keyset, но никто не сохраняет свой первоначальный заказ, и я в конечном итоге получить результат несортированный. Помощь & Подсказки приветствуются!

ответ

2

Я не знаю Groovy, поэтому я могу только прокомментировать Java.

A TreeMap сохраняет записи, отсортированные по ключам, а не значениям. В вашем случае он использует естественный порядок String s.

Если вы хотите Map для поддержания порядка вставки, используйте LinkedHashMap. Если вы это сделаете, вам нужно будет изменить тип возврата на Map<String, Integer>.

Я не могу написать подробный код, как я неясно о типах некоторых из ваших переменных, но основные шаги:

  1. Сортировка Listkeywords на основе value поля.
  2. Map<String, Integer> map = new LinkedHashMap<String, Integer>();
  3. Итерация в течение первых n элементов в keywords и заполнить map. Поскольку вы используете LinkedHashMap, записи останутся в правильном порядке.
  4. return map;
+0

Резкий. Проблема в том, что когда я назначаю ключевые слова = keywords.sort {...}, ключевые слова снова сортируются по ключу из-за природы TreeMap! После того, как я сменил его на LinkedHashMap, все пошло по плану! – OrlandoL

1

Как из вашего кода, кажется, вы используете заводным, вот как вы можете это сделать в заводном используя for loop

TreeMap<String,Integer> result = new TreeMap<>() 
    for(def entry : keywords) { 
     result[entry.key] = entry.value 

     n-- 
     if(n == 0) 
      break 
    } 

    return result 
5

Вы можете получить entrySet() из отсортированных карт, который ведет себя более или менее как список и получает диапазон от него:

def getKeywords(Map keywords, int itensQty){ 
    def sorted=keywords.sort{ a, b -> 
     b.value <=> a.value; 
    } 
    sorted.entrySet().toList()[0..<itensQty] 
} 


keywords = ["a": 90, "b": 110, "c": 70, "d": 130] 

assert getKeywords(keywords, 2) == ["d": 130, "b": 110].entrySet().toList() 
+0

Черт, ты избил меня к нему - чуть проще: 'keywords.entrySet(). Sort {-it.value} [0 .. cjstehno

+0

Это опрятное решение. Жаль, что я не могу принять оба ответа для одного и того же потока! – OrlandoL