Estoy buscando una biblioteca similar en funcionalidad al módulo Perl Lingua::EN::NameParse. Básicamente, me gustaría analizar cadenas como 'Mr. Bob R. Smith en los componentes de prefijo, nombre, apellido y sufijo de nombre. Google no ha sido de mucha ayuda para encontrar algo como esto y preferiría no rodar el mío si es posible. ¿Alguien sabe de una biblioteca OSS Java que puede hacer esto de una manera sofisticada?¿Qué es la biblioteca de análisis de nombre de Java?
Respuesta
Personalmente, optaría por regular expressions. Aquí hay un buen intro. Son rápidos, concisos y siempre hagan lo que quieran.
Si quiere mantenerse dentro de los límites de java SDK, use String tokenizers.
Un poco más bajo nivel es JavaCC, un generador de analizador basado en Java. Aquí hay un link to a tutorial.
Una alternativa a javaCC es ANTLR, con la que personalmente he tenido buenas experiencias.
Este código simple puede ayudar:
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;
}
}
Por ejemplo esta entrada:
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);
tiene esta salida:
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.]
No puedo creer que alguien no ha compartido una biblioteca para esto - bueno miré GitHub y hay un nombre analizador javascript que podría traducirse fácilmente a java: https://github.com/joshfraser/JavaScript-Name-Parser
También he modificado el código en una de las respuestas que trabajar un poco mejor y han incluido un caso de prueba:
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;
}
}
prueba 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());
}
}
}
El método isOneOf deben reescribirse como: isOneOf private boolean (cadena checkStr, títulos String []) { para (título de la cadena: títulos) if (checkStr.equalsIgnoreCase (title)) return true; devuelve falso; } Porque actualmente, reconocerá todos los nombres comenzando con una V como sufijo. – KimvdLinde
Apache Commons tiene la clase HumanNameParser.
Name nextName = parser.parse("James C. ('Jimmy') O'Dell, Jr.")
String firstName = nextName.getFirstName();
String nickname = nextName.getNickName();
Puede encontrarlo en [github] (https://github.com/apache/commons-text/blob/master/src/main/java/org/apache/commons/text/names/HumanNameParser.java).La versión actual todavía es SNAPSHOT sin embargo. –
- 1. Biblioteca Java para análisis de código
- 2. JAVA - Biblioteca de análisis y evaluación de expresiones
- 3. Análisis de Java/XSD
- 4. Android: ¿la mejor biblioteca de análisis XML?
- 5. ¿Qué es la Biblioteca de MVC Futures?
- 6. ¿Qué nombre de paquete debo usar para la biblioteca Java de código abierto?
- 7. En el nombre de la propiedad de Java, ¿qué nombre es más correcto?
- 8. C++ Sentimiento Análisis Biblioteca
- 9. Biblioteca de análisis de ecuaciones C++
- 10. ¿Qué es el análisis de paquetes?
- 11. ¿Qué es el análisis de código estático?
- 12. Biblioteca de análisis para aplicaciones iOS
- 13. ¿Qué biblioteca html DOM parser para Java es la mejor?
- 14. ¿Cuál es la biblioteca de análisis de fuentes más utilizada para Android?
- 15. ¿Qué es la biblioteca libg2c?
- 16. ¿La mejor biblioteca de iCalendar para Java?
- 17. Análisis monoidal - ¿qué es eso?
- 18. ¿Por qué se eligió el nombre "Hibernate" para la biblioteca Hibernate de Java?
- 19. ¿Qué biblioteca de Colecciones Java recomienda?
- 20. ¿Qué es el análisis especulativo?
- 21. ¿Qué biblioteca de validación java debo usar?
- 22. ¿Cuál es la biblioteca más madura para construir una canalización de análisis de datos en Java/Scala para Hadoop?
- 23. ¿Cuál es la mejor biblioteca matemática para usar con Java?
- 24. Buscar el nombre de la distribución de Linux de java
- 25. Análisis de Java de identificadores de puntos
- 26. Java análisis de registro de GC
- 27. Qué efecto tiene $ en un nombre de clase de Java
- 28. Análisis de escape en Java
- 29. Lectura y análisis de excepciones de Java
- 30. ¿Cuál es la mejor biblioteca de Java OXM?
+1 ¿Me puede mostrar un ejemplo de cómo analizar los nombres utilizando GATE –