2016-06-10 5 views
0

Ich habe eine Liste von Strings mit Namen und Nachnamen und ich habe einen freien Text.Java Regex in einem Text alle möglichen Paare einer Liste zu finden

List<String> names; // contains: "jon", "snow", "arya", "stark", ... 
String text = "jon snow and stark arya"; 

Ich habe alle Namen und Vornamen zu finden, die möglicherweise mit einem Java Regex (so mit Mustern und Objekten Matcher). Deshalb möchte ich so etwas wie:

List<String> foundNames; // contains: "jon snow", "stark arya" 

Ich habe dieses Bild 2 Möglichkeiten gemacht, aber ohne Regex zu verwenden, sie sind nicht statisch beacause Teil einer Klasse, die Namefinder eine Liste „Namen“, die alle Namen enthält.

public List<String> findNamePairs(String text) { 
    List<String> foundNamePairs = new ArrayList<String>(); 
    List<String> names = this.names; 
    text = text.toLowerCase(); 

    for (String name : names) { 
     String nameToSearch = name + " "; 
     int index = text.indexOf(nameToSearch); 
     if (index != -1) { 
      String textSubstring = text.substring(index + nameToSearch.length()); 
      for (String nameInner : names) { 
       if (name != nameInner && textSubstring.startsWith(nameInner)) { 
        foundNamePairs.add(name + " " + nameInner); 
       } 
      } 
     } 
    } 

    removeDuplicateFromList(foundNamePairs); 

    return foundNamePairs; 
} 

oder in einem schlechteren (sehr schlecht) Art und Weise (alle möglichen Paare zu schaffen):

public List<String> findNamePairsInTextNotOpt(String text) { 
    List<String> foundNamePairs = new ArrayList<String>(); 
    text = text.toLowerCase(); 
    List<String> pairs = getNamePairs(this.names); 

    for (String name : pairs) { 
     if (text.contains(name)) { 
      foundNamePairs.add(name); 
     } 
    } 

    removeDuplicateFromList(foundNamePairs); 

    return foundNamePairs; 
} 
+1

Was genau ist die Frage? –

+0

Warum würden Sie Regex verwenden, um das zu tun? – explv

+0

@JohnBellinger, ich werde versuchen, es in einem Moment besser zu erklären. Allerdings muss ich tun, was ich in einer "normalen" Methode mit Java Regex gemacht habe. –

Antwort

0

Sie einen regulären Ausdruck erstellen können, die Liste der Namen und anschließend finden, um die Namen zu finden. Um sicherzustellen, dass keine Duplikate vorhanden sind, können Sie überprüfen, ob der Name bereits in der Liste der gefundenen Namen enthalten ist. Der Code würde so aussehen. empfindlich entfernen Sie einfach das Flag in Pattern.compile()

List<String> names = Arrays.asList("jon", "snow", "stark", "arya"); 
String text = "jon snow and Stark arya and again Jon Snow"; 

StringBuilder regexBuilder = new StringBuilder(); 

for (int i = 0; i < names.size(); i += 2) { 
    regexBuilder.append("(") 
     .append(names.get(i)) 
     .append(" ") 
     .append(names.get(i + 1)) 
     .append(")"); 
    if (i != names.size() - 2) regexBuilder.append("|"); 
} 

System.out.println(regexBuilder.toString()); 

Pattern compile = Pattern.compile(regexBuilder.toString(), Pattern.CASE_INSENSITIVE); 

Matcher matcher = compile.matcher(text); 

List<String> found = new ArrayList<>(); 

int start = 0; 
while (matcher.find(start)) { 
    String match = matcher.group().toLowerCase(); 

    if (!found.contains(match)) found.add(match); 
    start = matcher.end(); 
} 

for (String s : found) System.out.println("found: " + s); 

Wenn Sie Fall sein wollen. Wenn alle Übereinstimmungen die gleiche Großschreibung haben, können Sie die toLowerCase() in der While-Schleife auch weglassen.

Aber stellen Sie sicher, dass die Liste ein Vielfaches von 2 als Listenelemente (Name und Vorname) enthält, da die for-Schleife andernfalls IndexOutOfBoundsException wirft. Auch die Reihenfolge zählt in meinem Code. Es findet nur die Namenspaare in der Reihenfolge, in der sie in der Liste vorkommen. Wenn Sie beide Aufträge haben möchten, können Sie die Regex-Generierung entsprechend ändern.

Edit: Da es unbekannt ist, ob ein Name ein Nachname oder Name ist und welche ein Name/Nachnamen-Paar bilden, muss die Regex-Generation anders gemacht werden.

StringBuilder regexBuilder = new StringBuilder("("); 

for (int i = 0; i < names.size(); i++) { 
    regexBuilder.append("(") 
      .append(names.get(i)) 
      .append(")"); 
    if (i != names.size() - 1) regexBuilder.append("|"); 
} 

regexBuilder.append(") "); 
regexBuilder.append(regexBuilder); 
regexBuilder.setLength(regexBuilder.length() - 1); 


System.out.println(regexBuilder.toString()); 

Dieser Regex wird mit jedem der angegebenen Namen übereinstimmen, gefolgt von einem Leerzeichen und dann wieder alle Namen.

+0

danke für die Hilfe, ich habe nicht sehr gut angegeben, dass in meiner Liste habe ich Namen und Nachnamen gemischt. So kann die Liste sein: Liste Namen = Arrays.asList ("Name1", "Name2", "Nachname2", "Nachname1"); Also kann ich nicht die Regex (element1 element2) | (element3 element4), ich muss alle möglichen Kombinationen setzen und ich befürchte, dass es sehr langsam sein kann. –

+0

Nun müssen Sie alle Kombinationen testen, da Sie keine Informationen darüber haben, welcher Name und Nachname zusammen gehören, sowie nicht wissen, ob ein Name ein Name oder ein Nachname ist. Ich werde der Antwort einen Abschnitt hinzufügen, um eine Regex dafür zu generieren. – Leon

Verwandte Themen