Avatar billede superanden Nybegynder
11. maj 2007 - 09:17 Der er 8 kommentarer og
2 løsninger

Sorter ArrayListe efter hyppighed

Hej eksperter,

Jeg sidder med et problem: Jeg har en dynamisk arraylist f.eks. [hej , med , dig] , til denne vil jeg gerne have lavet en mulighed for at få den sorteret i forhold til hvor tit ordene har været brugt.

Jeg skal altså have lavet en anden liste, set, map, hvor frekvensen af hvert ord ligger.

Jeg havde selv tænkt på at lave et hashmap indeholdende strenge som nøgler og værdien skal så være et heltal som repræsentere det antal gange hver streng har været brugt, og så en funktion der hver gang man bruger et ord tilføjer det til hasmappet medmindre det allerede ligger der så skal det bare lægge en til værdien. Dette er ikke så stort et problem.

Der hvor problemet opstår er når jeg skal have min arraylist [hej , med , dig] sorteret i forhold til de værdier jeg kan slå op i mit hashmap. Jeg er helt lost på hvordan dette kan gøres, så har virkelig brug for hjælp.

//Superanden
Avatar billede iskanu Nybegynder
11. maj 2007 - 10:34 #1
package hyppighed;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

public class FrequencySort {
public static void main(String[] args) {

//What we have
ArrayList<String> strings = new ArrayList<String>();
HashMap<String,Integer> frequencies = new HashMap<String,Integer>();

//Add test values
strings.add("a");
strings.add("b");
strings.add("c");

frequencies.put("a", 3);
frequencies.put("b", 5);
frequencies.put("c", 3);

ArrayList<String> sortedStrings = frequencySort(frequencies);

for(int i = 0 ; i < sortedStrings.size(); i++){
    System.out.println(sortedStrings.get(i));
}
}

private static ArrayList<String> frequencySort(HashMap<String, Integer> frequencies) {

//create a hashmap with frequencies as keys, and lists of words
//with the same frequencies as values
HashMap<Integer, ArrayList<String>> bookkeeper = new HashMap<Integer, ArrayList<String>>();
ArrayList<String> samefrequencywords;
int frequency;
for(String word : frequencies.keySet()){
    frequency = frequencies.get(word);
    samefrequencywords = bookkeeper.get(frequency);
    if(samefrequencywords == null){
        samefrequencywords = new ArrayList<String>();
        bookkeeper.put(frequency, samefrequencywords);
    }
    samefrequencywords.add(word);
}

//sort the individual frequencies
ArrayList<Integer> frequencyList = new ArrayList<Integer>();
frequencyList.addAll(bookkeeper.keySet());
Collections.sort(frequencyList);

//create 1 list with all words. same frequency words are
//inserted in arbitary order.
ArrayList<String> sortedStrings = new ArrayList<String>();
int key;
for(int i = 0; i < frequencyList.size(); i++){//bookkeeper.size == frequencyList.size
    key = frequencyList.get(i);
    samefrequencywords = bookkeeper.get(key);
    for(int j = 0; j < samefrequencywords.size(); j++){
        sortedStrings.add(samefrequencywords.get(j));
    }
}

return sortedStrings;
}
}
Avatar billede bauerdata Nybegynder
11. maj 2007 - 10:48 #2
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""Usage: python wordsortcount.py <filnavn>
    <filnavn> tekstfil
"""
import sys, os

def cmp_antal(x , y):
    return cmp(x[1],y[1])

if __name__ == "__main__":
    try:
        FName = sys.argv[ 1 ]
    except:
        print "mangler filnavn"
        print __doc__
        sys.exit( 1 )

    file = open( FName )
    worddict = {}  # Hash key build in python type

    text = file.read().strip()
   
    for line in text.splitlines():
        words = line.split()
        for word in words:
            if worddict.has_key( word ):
                worddict[word] = worddict[word] + 1
            else: # First time word is found
                worddict[word] = 1
               
    res_list = worddict.items()
    res_list.sort(cmp_antal)
    for ( word, antal ) in res_list:
        print "%(word)-25s, %(antal)d" % vars()
Avatar billede iskanu Nybegynder
11. maj 2007 - 10:50 #3
Jeg har kompilleret med Java 1.6, da koden bruger autoboxing.
strings: [a, b, c]
frequencies: [a=3, b=5, c=3]
bookkeeper: [3=[c, a] 5=[b]]

strings listen bliver ikke brugt til noget, den er med fordi du nævner det i din problemstilling.

frequencyList = [3, 5]
i sidste blok i frequencySort metoden:
1.) vi tager de individuelle frekvenser i stigende rækkefølge fra frequencyList,
2.) vi tager de til den givne frekvens hørende liste med strings (disse har samme frekvens)
3.) og sætter dem ind i sortedStrings listen.

For de strings der har samme frekvens er der ikke defineret nogen sorteringsregel.
Avatar billede superanden Nybegynder
11. maj 2007 - 11:00 #4
Fedt iskanu.rigtig fedt, hurtigt om med kommentarer... men hvordan ændre jeg så den sorterer i faldende rækkefølge.? altså de højeste frekvenser først.? har på fornemmelse at det er noget der ligger i collections.sort() kan bare ikke lige gennemskue hvordan..
Avatar billede iskanu Nybegynder
11. maj 2007 - 11:10 #5
Jeg har i svaret fokuseret på den centrale problemstilling: sortere efter "values" i din HashMap. Jeg har brugt Collections.sort() for jeg ville ikke implementere en sorteringsalgoritme. Du kan gøre det og få fuld kontrol over sorteringen.

Alternativt kan du bare læse ArrayList'en baglæns:
for(int i = sortedStrings.size() - 1, i >= 0; i--){
    System.out.println(sortedStrings.get(i));
}

Du kan gøre dette før du sender resultatet retur fra metoden, så main() får det du har specificeret.
Avatar billede iskanu Nybegynder
11. maj 2007 - 11:14 #6
Du kan også ændre den 3. blok "//create 1 list with..." så den bygger din retur liste, så er du fri for at kopiere den en gang til.
Avatar billede iskanu Nybegynder
11. maj 2007 - 15:35 #7
Husk at give points når du har fået svar på dit spørgsmål :-)
Avatar billede arne_v Ekspert
12. maj 2007 - 03:14 #8
et alternativt forslag til frequencySort:

    private static ArrayList<String> frequencySort(final HashMap<String, Integer> frequencies) {
        ArrayList<String> strings = new ArrayList<String>();
        strings.addAll(frequencies.keySet());
        Collections.sort(strings, new Comparator<String>() {
            public int compare(String s1, String s2) {
                return frequencies.get(s1) - frequencies.get(s2);
            } });
        return strings;
    }
Avatar billede bauerdata Nybegynder
12. maj 2007 - 13:00 #9
# Med revese order 
    file = open( FName )
    worddict = {}  # Hash key build in python type

    text = file.read().strip()

    for line in text.splitlines():
        words = line.split()
        for word in words:
            if worddict.has_key( word ):
                worddict[word] = worddict[word] + 1
            else: # First time word is found
                worddict[word] = 1
             
    res_list = worddict.items()
    res_list.sort(cmp_antal)
    res_list.reverse()
Avatar billede arne_v Ekspert
12. maj 2007 - 15:09 #10
bauerdata>

Kategorien hedder Java ikke Python.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester