Sto cercando una libreria simile nella funzionalità al modulo Perl Lingua::EN::NameParse. In sostanza, mi piacerebbe analizzare stringhe come "Mr. Bob R. Smith 'in prefisso, nome, cognome e componenti del suffisso del nome. Google non è stato di grande aiuto nel trovare qualcosa di simile e preferirei non lanciare il mio, se possibile. Qualcuno sa di una libreria Java OSS che può farlo in un modo sofisticato?Libreria di analisi nome Java?
risposta
Personalmente, opterei per regular expressions. Ecco un buon intro. Sono veloci, concisi e sempre fai quello che vuoi.
Se si desidera rimanere entro i limiti del sdk java, utilizzare String tokenizers.
Un po 'più di basso livello è JavaCC, un generatore di parser basato su Java. Ecco uno link to a tutorial.
Un'alternativa a javaCC è ANTLR, con cui ho avuto personalmente esperienze positive.
Questo semplice codice può aiutare:
import java.util.ArrayList;
import java.util.List;
public class NamesConverter {
private List<String> titlesBefore = new ArrayList<>();
private List<String> titlesAfter = new ArrayList<>();
private String firstName = "";
private String lastName = "";
private List<String> middleNames = new ArrayList<>();
public NamesConverter(String name) {
String[] words = name.split(" ");
boolean isTitleAfter = false;
boolean isFirstName = false;
int length = words.length;
for (String word : words) {
if (word.charAt(word.length() - 1) == '.') {
if (isTitleAfter) {
titlesAfter.add(word);
} else {
titlesBefore.add(word);
}
} else {
isTitleAfter = true;
if (isFirstName == false) {
firstName = word;
isFirstName = true;
} else {
middleNames.add(word);
}
}
}
if (middleNames.size() > 0) {
lastName = middleNames.get(middleNames.size() - 1);
middleNames.remove(lastName);
}
}
public List<String> getTitlesBefore() {
return titlesBefore;
}
public List<String> getTitlesAfter() {
return titlesAfter;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<String> getMiddleNames() {
return middleNames;
}
@Override
public String toString() {
String text = "Titles before :" + titlesBefore.toString() + "\n"
+ "First name :" + firstName + "\n"
+ "Middle names :" + middleNames.toString() + "\n"
+ "Last name :" + lastName + "\n"
+ "Titles after :" + titlesAfter.toString() + "\n";
return text;
}
}
Per esempio questo ingresso:
NamesConverter ns = new NamesConverter("Mr. Dr. Tom Jones");
NamesConverter ns1 = new NamesConverter("Ing. Tom Ridley Bridley Furthly Murthly Jones CsC.");
System.out.println(ns);
System.out.println(ns1);
ha questa uscita:
Titles before :[Mr., Dr.]
First name :Tom
Middle names :[]
Last name :Jones
Titles after :[]
Titles before :[Ing.]
First name :Tom
Middle names :[Ridley, Bridley, Furthly, Murthly]
Last name :Jones
Titles after :[CsC.]
Non riesco a credere che qualcuno non ha condiviso una libreria per questo - beh, ho guardato dentro github e c'è un nome parser javascript che potrebbe facilmente essere tradotto a java: https://github.com/joshfraser/JavaScript-Name-Parser
ho anche modificato il codice in una delle risposte a lavorare un po 'meglio e hanno incluso un banco di prova:
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
public class NameParser {
private String firstName = "";
private String lastName = "";
private String middleName = "";
private List<String> middleNames = new ArrayList<String>();
private List<String> titlesBefore = new ArrayList<String>();
private List<String> titlesAfter = new ArrayList<String>();
private String[] prefixes = { "dr", "mr", "ms", "atty", "prof", "miss", "mrs" };
private String[] suffixes = { "jr", "sr", "ii", "iii", "iv", "v", "vi", "esq", "2nd", "3rd", "jd", "phd",
"md", "cpa" };
public NameParser() {
}
public NameParser(String name) {
parse(name);
}
private void reset() {
firstName = lastName = middleName = "";
middleNames = new ArrayList<String>();
titlesBefore = new ArrayList<String>();
titlesAfter = new ArrayList<String>();
}
private boolean isOneOf(String checkStr, String[] titles) {
for (String title : titles) {
if (checkStr.toLowerCase().startsWith(title))
return true;
}
return false;
}
public void parse(String name) {
if (StringUtils.isBlank(name))
return;
this.reset();
String[] words = name.split(" ");
boolean isFirstName = false;
for (String word : words) {
if (StringUtils.isBlank(word))
continue;
if (word.charAt(word.length() - 1) == '.') {
if (!isFirstName && !this.isOneOf(word, prefixes)) {
firstName = word;
isFirstName = true;
} else if (isFirstName) {
middleNames.add(word);
} else {
titlesBefore.add(word);
}
} else {
if (word.endsWith(","))
word = StringUtils.chop(word);
if (isFirstName == false) {
firstName = word;
isFirstName = true;
} else {
middleNames.add(word);
}
}
}
if (middleNames.size() > 0) {
boolean stop = false;
List<String> toRemove = new ArrayList<String>();
for (int i = middleNames.size() - 1; i >= 0 && !stop; i--) {
String str = middleNames.get(i);
if (this.isOneOf(str, suffixes)) {
titlesAfter.add(str);
} else {
lastName = str;
stop = true;
}
toRemove.add(str);
}
if (StringUtils.isBlank(lastName) && titlesAfter.size() > 0) {
lastName = titlesAfter.get(titlesAfter.size() - 1);
titlesAfter.remove(titlesAfter.size() - 1);
}
for (String s : toRemove) {
middleNames.remove(s);
}
}
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getMiddleName() {
if (StringUtils.isBlank(this.middleName)) {
for (String name : middleNames) {
middleName += (name + " ");
}
middleName = StringUtils.chop(middleName);
}
return middleName;
}
public List<String> getTitlesBefore() {
return titlesBefore;
}
public List<String> getTitlesAfter() {
return titlesAfter;
}
}
test case:
import junit.framework.Assert;
import org.junit.Test;
public class NameParserTest {
private class TestData {
String name;
String firstName;
String lastName;
String middleName;
public TestData(String name, String firstName, String middleName, String lastName) {
super();
this.name = name;
this.firstName = firstName;
this.lastName = lastName;
this.middleName = middleName;
}
}
@Test
public void test() {
TestData td[] = { new TestData("Henry \"Hank\" J. Fasthoff IV", "Henry", "\"Hank\" J.", "Fasthoff"),
new TestData("April A. (Caminez) Bentley", "April", "A. (Caminez)", "Bentley"),
new TestData("fff lll", "fff", "", "lll"),
new TestData("fff mmmmm lll", "fff", "mmmmm", "lll"),
new TestData("fff mmm1 mm2 lll", "fff", "mmm1 mm2", "lll"),
new TestData("Mr. Dr. Tom Jones", "Tom", "", "Jones"),
new TestData("Robert P. Bethea Jr.", "Robert", "P.", "Bethea"),
new TestData("Charles P. Adams, Jr.", "Charles", "P.", "Adams"),
new TestData("B. Herbert Boatner, Jr.", "B.", "Herbert", "Boatner"),
new TestData("Bernard H. Booth IV", "Bernard", "H.", "Booth"),
new TestData("F. Laurens \"Larry\" Brock", "F.", "Laurens \"Larry\"", "Brock"),
new TestData("Chris A. D'Amour", "Chris", "A.", "D'Amour") };
NameParser bp = new NameParser();
for (int i = 0; i < td.length; i++) {
bp.parse(td[i].name);
Assert.assertEquals(td[i].firstName, bp.getFirstName());
Assert.assertEquals(td[i].lastName, bp.getLastName());
Assert.assertEquals(td[i].middleName, bp.getMiddleName());
}
}
}
Il metodo isOneOf dovrebbe essere riscritto come: isOneOf privato booleani (String checkStr, titoli String []) { per (Titolo stringa: titoli) if (checkStr.equalsIgnoreCase (title)) return true; return false; } Perché attualmente riconoscerà tutti i nomi che iniziano con una V come suffisso. – KimvdLinde
Apache Commons ha la classe HumanNameParser.
Name nextName = parser.parse("James C. ('Jimmy') O'Dell, Jr.")
String firstName = nextName.getFirstName();
String nickname = nextName.getNickName();
Puoi trovarlo su [github] (https://github.com/apache/commons-text/blob/master/src/main/java/org/apache/commons/text/names/HumanNameParser.java).La versione corrente è comunque SNAPSHOT. –
- 1. Nome qualificato dell'assemblaggio di analisi?
- 2. Libreria di analisi numero di telefono .NET
- 3. Android: la migliore libreria di analisi XML?
- 4. Libreria di analisi del sentiment C++
- 5. Errore di analisi Java LocalDateTime
- 6. di analisi JSON file Java
- 7. Java codice statico analisi
- 8. Hibernate Tools: errore di nome JNDI analisi
- 9. Analisi bytecode in Java
- 10. Analisi log GC Java
- 11. Analisi di documenti RTF con Java/JavaCC
- 12. Lettura e analisi KML in java
- 13. Java String analisi - {k1 = v1, v2 = k2, ...}
- 14. Libreria di tessere iperboliche Libreria Java
- 15. Collisioni nome libreria condivisa
- 16. cronexpression analisi in data java
- 17. Java decimale problema Format analisi
- 18. analisi di un tavolo utilizzando regex - Java
- 19. MongoDB + Java - analisi di JSON tramite com.mongodb.util.JSON.parse
- 20. JsonPath Errore di analisi JSON in java
- 21. Java Math (s) API di analisi
- 22. Analisi della data di scostamento Java 8
- 23. Analisi statica del grafo di chiamata Java
- 24. Analisi di JSON in Java senza conoscere il formato JSON
- 25. Libreria di crittografia bidirezionale Java
- 26. Libreria di geometria per Java
- 27. Libreria di valute per Java
- 28. Libreria di scrittura CSS Java
- 29. Libreria gateway di pagamento Java
- 30. Analisi di dati binari ASN.1 con Java
+1 Puoi mostrarmi un esempio di come analizzare i nomi che utilizzano GATE –