Man hat einen Projektnamen String = "k1000000000-1212-21241-model-KI";
Und eine Liste aus Wörtern woraus man das beste Raussuchen soll was zu dem Projektnamen passt.
Dazu folgender Algorithmus:
Coverten damit der Test geht:
Und ich würde gerne wissen ob das besser geht/ob ich große fehler mache?
Wichtig! Keine Libraries oder so in der Art.
Vielen Dank im voraus fürs Helfen und Testen 🙂
LG Elija
Und eine Liste aus Wörtern woraus man das beste Raussuchen soll was zu dem Projektnamen passt.
Code:
@Test
void test144_k80100() {
String projektname = "k80100_5144_000-basismodul-model";
assertEquals("144_k80100", workingSets1.getBestermatch(projektname));
}
Dazu folgender Algorithmus:
Java:
package Phillip;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
public class ProjektnamenSortierer {
private final String projektname;
private final ArrayList<String> allesuchbegriffe;
private final String bestermatch;
public ProjektnamenSortierer(String projektname, ArrayList<String> allesuchbegriffe) {
this.projektname = projektname;
this.allesuchbegriffe = new ArrayList<>(allesuchbegriffe);
this.bestermatch = findBestMatch();
}
private String normalisieren(String text) {
return text.toLowerCase(Locale.ROOT);
}
// Zerlegt den Projektnamen in Tokens(Teile)...
private Set<String> zerlegeProjektname(String name) {
Set<String> tokens = new HashSet<>();
String normalisiert = normalisieren(name);
StringBuilder version = new StringBuilder();
for (char c : normalisiert.toCharArray()) {
if (Character.isDigit(c)) {
version.append(c);
} else if (c == '.' || c == '-') {
// Trenner innerhalb einer Version ignorieren
} else {
if (version.length() > 0) {
if (version.length() >= 3) {
tokens.add(version.toString());
}
version.setLength(0);
}
}
}
if (version.length() >= 3) {
tokens.add(version.toString());
}
String[] teile = normalisiert.split("[\\-_.\\s]+");
for (String teil : teile) {
if (!teil.isBlank()) {
tokens.add(teil);
}
}
return tokens;
}
// Zerlegt Suchbegriffe
private List<String> zerlegeSuchbegriff(String begriff) {
List<String> teile = new ArrayList<>();
for (String teil : begriff.split("_")) {
teil = teil.trim();
if (!teil.isEmpty()) {
teile.add(teil);
}
}
return teile;
}
private boolean istTechnischeKennung(String text) {
for (char c : text.toCharArray()) {
if (Character.isDigit(c)) {
return true;
}
}
return false;
}
private String entferneVersionsTrenner(String text) {
return text.replace(".", "").replace("-", "");
}
// Prüft ob ein Teil im Projekt gefunden wird
private boolean passt(String suchteil, String projektLower, Set<String> projektTokens) {
String teil = normalisieren(suchteil);
if (projektTokens.contains(teil)) {
return true;
}
if (projektLower.contains(teil)) {
return true;
}
String bereinigt = entferneVersionsTrenner(teil);
if (bereinigt.isEmpty())
return false;
if (!bereinigt.equals(teil) && projektLower.contains(bereinigt)) {
return true;
}
boolean nurZiffern = true;
for (char c : bereinigt.toCharArray()) {
if (!Character.isDigit(c)) {
nurZiffern = false;
break;
}
}
if (nurZiffern) {
for (String token : projektTokens) {
if (token.equals(bereinigt)) {
return true;
}
// 5142 -> 142
// 5144 -> 144
if (token.endsWith(bereinigt)) {
return true;
}
}
}
return false;
}
// TODO Ist das schon gerhard coded? -> Phillip fragen!
// Marker-Teile - die nicht im Projektnamen vorkommen müssen
private static final Set<String> OPTIONALE_MARKER = Set.of("kv");
private boolean istOptionalerMarker(String teil) {
return OPTIONALE_MARKER.contains(normalisieren(teil));
}
// Prüft ob alle Bestandteile gefunden wurden
private boolean istVolltreffer(String begriff, String projektLower, Set<String> projektTokens) {
List<String> teile = zerlegeSuchbegriff(begriff);
if (teile.isEmpty()) {
return false;
}
boolean mindestensEinEchterTreffer = false;
for (String teil : teile) {
if (istOptionalerMarker(teil)) {
continue; // muss nicht im Projekt vorkommen
}
if (!passt(teil, projektLower, projektTokens)) {
return false;
}
mindestensEinEchterTreffer = true;
}
return mindestensEinEchterTreffer;
}
// Bewertet Volltreffer
private int berechneVolltrefferScore(String begriff) {
List<String> teile = zerlegeSuchbegriff(begriff);
int technischeTeile = 0;
int laenge = 0;
for (String teil : teile) {
laenge += teil.length();
if (istTechnischeKennung(teil)) {
technischeTeile++;
}
}
return technischeTeile * 10000 + teile.size() * 1000 + laenge;
}
// Bewertet Teiltreffer
private int berechneTeiltrefferScore(String begriff, String projektLower, Set<String> projektTokens) {
List<String> teile = zerlegeSuchbegriff(begriff);
int treffer = 0;
int technischeTreffer = 0;
for (String teil : teile) {
if (passt(teil, projektLower, projektTokens)) {
treffer++;
if (istTechnischeKennung(teil)) {
technischeTreffer++;
}
}
}
if (treffer == 0) {
return -1;
}
return treffer * 100000 + technischeTreffer * 10000 + teile.size() * 1000;
}
// Sucht den besten Treffer.
private String findBestMatch() {
String projektLower = normalisieren(projektname);
Set<String> projektTokens = zerlegeProjektname(projektname);
String besterTreffer = "0";
int besterScore = -1;
// Phase 1: Nur Volltreffer
for (String begriff : allesuchbegriffe) {
if (begriff == null || begriff.isBlank()) {
continue;
}
if (istVolltreffer(begriff, projektLower, projektTokens)) {
int score = berechneVolltrefferScore(begriff);
if (score > besterScore) {
besterScore = score;
besterTreffer = begriff;
}
}
}
if (besterScore >= 0) {
return besterTreffer;
}
// Phase 2: Teiltreffer
for (String begriff : allesuchbegriffe) {
if (begriff == null || begriff.isBlank()) {
continue;
}
int score = berechneTeiltrefferScore(begriff, projektLower, projektTokens);
if (score > besterScore) {
besterScore = score;
besterTreffer = begriff;
}
}
return besterTreffer;
}
public String getBestermatch() {
return bestermatch;
}
}
Coverten damit der Test geht:
Java:
package Phillip;
import java.util.ArrayList;
import java.util.Arrays;
public class BestMatchFinder {
private final ArrayList<String> suchbegriffe;
public BestMatchFinder(String... suchbegriffe) {
this.suchbegriffe = new ArrayList<>(Arrays.asList(suchbegriffe));
}
public String getBestermatch(String projektname) {
ProjektnamenSortierer sortierer = new ProjektnamenSortierer(projektname, suchbegriffe);
return sortierer.getBestermatch();
Und ich würde gerne wissen ob das besser geht/ob ich große fehler mache?
Wichtig! Keine Libraries oder so in der Art.
Vielen Dank im voraus fürs Helfen und Testen 🙂
LG Elija