Wie schon im Titel beschrieben brauche ich einen Container, der in der Lage ist eine bestimmte Datenstruktur zu speichern und vernünftig ansprechbar zu machen:
Mein derzeitiger Ansatz ist der folgende:
Hier sind die dazugehörigen relevanten aufgerufenen Methoden:
und
Wobei die Methode WDFIDF ausschließlich Berechnungen durchführt und nicht relevant ist.
Um das ganze in einem Zusammenhang zu setzen: Man nehme einen Text, importiere diesen in einen String, splitte diesen String in einen StringArray mit jeder einzelnen Zeile drin.
Jede dieser Zeilen muss nun verarbeitet werden, dazu wird sie wiederum in einen StringArray mit allen beinhaltenden Wörtern gesplittet und analysiert.
Nun kommen wir zu meinem problem: Einerseits muss ich für jede Zeile eine HashMap mit allem vorkommenden Worten anlegen (umgeformt in einen TreeSet um das ganze nicht nur nach key, sondern auch nach value sortieren zu können), und andererseits muss ich eine Übersicht über den so entstehenden Korpus erhalten, wiederum eine HashMap, die ein TreeSet als value hat.
<String s, TreeSet<String s, Double d>>
Wie man im Code bereits sieht -->
versuche ich die so erstellten Daten irgendwie anzusprechen, und wie einen verschachtelten Array ausgeben zu lassen (was natürlich nicht dasselbe ist und anders implementiert wird). Dabei ist es meine Absicht für jede Zeile einen Korpus mit den einzelnen Wörtern und ihrer Gewichtung zu erhalten.
Was ich bekomme ist ein Gewurschtel aus Zeilen-Ausgaben, gefolgt von den Wort-Gewichtungs-Paaren, aber keine ordentliche Struktur, was das weiterverarbeiten der Daten unmöglich mach, geschweige denn das verstehen logischer Fehler meiner Implementation.
Nun stellt sich mir die Frage, ob ich diese Aufgabe mit den richtigen Mitteln angehe, oder es sinnvoller wäre ein selbst erstelltes Objekt zu formen und dieses in einer geeigneteren Datenstruktur abzuspeichern (falls dies möglich ist).
Mein derzeitiger Ansatz ist der folgende:
Java:
private void processDatabase(String databaseString) throws IOException {
String[] documentLines = databaseString.split("\\n");
int N = documentLines.length; // N int
String[] completeFilteredText = pk.filterStopwords(databaseString);
completeKeywords = pk.countKeywords(completeFilteredText);
completeKeywords.forEach((String key, Integer value) -> { // n HashMap<String, Integer>
int n = 0;
for (String line : documentLines) {
if (line.contains(String.valueOf(key))){
n++;
}
nKeywords.put(key, n);
}
});
infoJLabel.setText(completeKeywords.getOrDefault("INFO", 0).toString());
warnJLabel.setText(completeKeywords.getOrDefault("WARN", 0).toString());
errorJLabel.setText(completeKeywords.getOrDefault("ERROR", 0).toString());
debugJLabel.setText(completeKeywords.getOrDefault("DEBUG", 0).toString());
for (String documentLine : documentLines) {
documentLine = documentLine.replace("\n", " ");
sortedKeywords.clear();
//System.out.println("line: " + line);
String[] lineWords = documentLine.split(" ");
String[] documentFilteredText = pk.filterStopwords(documentLine);
keywords = pk.countKeywords(documentFilteredText);
sortedKeywords = rr.rankKeywords(keywords, lineWords[0], N, nKeywords);
keywordsPerDocument.put(lineWords[0], sortedKeywords);
}
keywordsPerDocument.forEach((String key, TreeSet<Entry<String, Double>> value) -> {
System.out.println("Key: " + key);
TreeSet<Entry<String, Double>> treeSet = keywordsPerDocument.get(key);
Iterator it = treeSet.iterator();
while (it.hasNext()) {
System.out.println("Keyword: " + it.next().toString());
}
});
}
Hier sind die dazugehörigen relevanten aufgerufenen Methoden:
Java:
public class ProcessKeywords {
public String[] filterStopwords(String text) throws IOException {
Pattern p1 = Pattern.compile( "[\\d*\\p{Punct}*]*" );
Pattern p2 = Pattern.compile( "\\d*" );
Pattern p3 = Pattern.compile( "\\p{Punct}*" );
//System.out.println(text);
text = text.replace("\\p{Punct}", " ");
String[] split = StringUtils.split(text, " ");
String filteredTextString = new String();
for (String s : split) {
s = s.trim();
Matcher m1 = p1.matcher(s);
Matcher m2 = p2.matcher(s);
Matcher m3 = p3.matcher(s);
if ( !m1.matches() && !m2.matches() && !m3.matches() && (s!=null) && (!s.equals(""))){
filteredTextString = filteredTextString + " " + s;
}
}
String[] filteredText = StringUtils.split(filteredTextString, " ");
return filteredText;
}
private HashMap<String, Integer> keywords = new HashMap<>();
public HashMap<String, Integer> countKeywords(String[] filteredText) {
for (String entry : filteredText) {
keywords.putIfAbsent(entry, 1);
if (keywords.containsKey(entry)) {
keywords.replace(entry, keywords.getOrDefault(entry, 0), keywords.getOrDefault(entry, 0) + 1);
}
}
return keywords;
}
und
Code:
public class RelevanceRanking {
private int terms;// Anzahl der Terme im Dokument
private double G;
private final WDFIDF wd = new WDFIDF();
private Map<String, Double> gewichtung;
private TreeSet<Map.Entry<String, Double>> sortedGewichtung = new TreeSet();
public TreeSet<Map.Entry<String, Double>> rankKeywords(HashMap<String, Integer> keywords, String text, int N, HashMap<String, Integer> nKeywords) throws IOException {
this.gewichtung = new TreeMap();
String[] split = text.split(" ");
for (String entry : split) {
entry = entry.trim();
keywords.putIfAbsent(entry, 1);
if (keywords.containsKey(entry)) {
keywords.replace(entry, keywords.get(entry), keywords.get(entry) + 1);
}
}
terms = split.length;
keywords.forEach((Object key, Object value) -> {
try {
//System.out.println(String.valueOf("Keyword zum gewichten: " + key));
G = wd.wdfidf(value.toString(), String.valueOf(terms), String.valueOf(N), String.valueOf(nKeywords.getOrDefault(key, 1)));
gewichtung.put((String) key, G);
} catch (IOException ex) {
Logger.getLogger(ProcessKeywords.class.getName()).log(Level.SEVERE, null, ex);
}
});
sortedGewichtung = entriesSortedByValues(gewichtung);
return sortedGewichtung;
}
static <K,V extends Comparable<? super V>>
TreeSet<Map.Entry<K,V>> entriesSortedByValues(Map<K,V> map) {
TreeSet<Map.Entry<K,V>> sortedEntries = new TreeSet<>(
(Map.Entry<K,V> e1, Map.Entry<K,V> e2) -> {
int res = e2.getValue().compareTo(e1.getValue());
return res != 0 ? res : 1;
});
sortedEntries.addAll(map.entrySet());
return sortedEntries;
}
}
Um das ganze in einem Zusammenhang zu setzen: Man nehme einen Text, importiere diesen in einen String, splitte diesen String in einen StringArray mit jeder einzelnen Zeile drin.
Jede dieser Zeilen muss nun verarbeitet werden, dazu wird sie wiederum in einen StringArray mit allen beinhaltenden Wörtern gesplittet und analysiert.
Nun kommen wir zu meinem problem: Einerseits muss ich für jede Zeile eine HashMap mit allem vorkommenden Worten anlegen (umgeformt in einen TreeSet um das ganze nicht nur nach key, sondern auch nach value sortieren zu können), und andererseits muss ich eine Übersicht über den so entstehenden Korpus erhalten, wiederum eine HashMap, die ein TreeSet als value hat.
<String s, TreeSet<String s, Double d>>
Wie man im Code bereits sieht -->
Java:
keywordsPerDocument.forEach((String key, TreeSet<Entry<String, Double>> value) -> {
System.out.println("Key: " + key);
TreeSet<Entry<String, Double>> treeSet = keywordsPerDocument.get(key);
Iterator it = treeSet.iterator();
while (it.hasNext()) {
System.out.println("Keyword: " + it.next().toString());
}
});
Was ich bekomme ist ein Gewurschtel aus Zeilen-Ausgaben, gefolgt von den Wort-Gewichtungs-Paaren, aber keine ordentliche Struktur, was das weiterverarbeiten der Daten unmöglich mach, geschweige denn das verstehen logischer Fehler meiner Implementation.
Nun stellt sich mir die Frage, ob ich diese Aufgabe mit den richtigen Mitteln angehe, oder es sinnvoller wäre ein selbst erstelltes Objekt zu formen und dieses in einer geeigneteren Datenstruktur abzuspeichern (falls dies möglich ist).