Je fais une migration de site Web qui implique d'extraire le prénom et le nom de famille de FullName. Compte tenu de ceux-ci ont été créés par l'utilisateur final, toutes sortes de permutations existent (bien que l'anglais et généralement pas trop étrange). La plupart du temps, je peux prendre le premier mot comme prénom et le dernier mot que le nom de famille, mais avoir des exceptions à partir du préfixe et du suffixe occasionnels. En passant par les données et en essayant de mettre ma tête autour de toutes les exceptions probables, j'ai réalisé qu'il s'agit d'un problème commun qui a été au moins partiellement résolu de plusieurs reprises auparavant. p>
Avant de réinventer la roue, quelqu'un a-t-il des expressions régulières qui ont fonctionné pour eux ou un code utile? La performance n'est pas une considération car il s'agit d'une utilité unique. p>
Valeurs typiques à traiter: P>
Jason Briggs, J.d. Smith, John Y Citoyen, J Scott Myers, Bill Jackobson III, M. John Mills P> blockQuote>
MISE À JOUR: Pendant un problème courant, la solution typique semble impliquer la manipulation de la majorité des cas et le nettoyage manuel du reste. p>
(Compte tenu de la fréquence, ce problème doit être expérimenté, j'attendais à l'origine de trouver une bibliothèque d'utilité, mais n'a pas été en mesure de trouver un moi-même avec Google) P>
10 Réponses :
S'il s'agit d'une affaire d'un coup, j'envisagerai fortement de payer quelqu'un d'autre qui est un spécialiste de le faire pour vous. P>
Ils seront expérimentés pour travailler avec des ensembles de données mal structurés. P>
Je n'ai aucune affiliation avec eux mais Data Melissa Fournir un service qui semble adapté à ce genre de chose. p>
Il est probablement impossible de faire (fiable). p>
Même si vous pouvez le faire pour certains noms, vous obtiendrez une personne espagnole à un moment donné, qui écrira les deux noms de famille. Ou certaines personnes (oublié quelle nationalité il est) qui mettra dans "Nom Prénom". Ou une des nombreuses situations ... p>
Le mieux que vous puissiez probablement faire est divisé 2 mots comme prénom et nom, puis passez à travers le reste manuellement (vous-même ou embaucher des professionnels) ... P>
Je pense que vous avez raison. Les permutations linguistiques et le plomb Nature non structuré font un problème indéterminé car APOORV a souligné.
Et n'oubliez pas les derniers noms de famille comme O'Neill et Van der Spek et Van Eck et Hart-Mahon et de la Cruz ...
Ceci est un problème indéterminé (ou un problème d'oracle que j'aime appeler cela) et est insoluble de manière fiable. C'est à cause de l'existence de noms qui sont à la fois des prénoms et des noms de famille, Stanley, Jackson, etc., mais un essai peut être donné. Vous devez écrire un programme d'apprentissage qui reçoive un ensemble de prénoms et de noms de famille et il conservera un dictionnaire de ces noms, mappé sur la probabilité qu'il s'agisse d'un prénom. P>
Maintenant, passez toutes vos valeurs à migrer et à utiliser ces probabilités, vous pouvez obtenir une scission raisonnable entre les prénoms et les noms de famille. De plus, si un nom particulier devient ambigu (totalement sur vous de définir une ambiguë, mais je la définirais comme les 30 centile inférieurs de toutes les valeurs de probabilité que j'ai obtenues), vous pouvez le signaler pour examen plus tard. P>
J'espère que cela aide. P>
acclamations! p>
De plus, pour des cas comme J.D. Smith, vous pouvez surtout traiter J.D. a été prénom et Smith comme nom de famille.
Ma recommandation serait la suivante: p>
diviser les noms sur les espaces. p> li>
Vérifiez la longueur de la matrice renvoyée. Si 2, fendu facile. Si plus, suivant. P> li>
comparer la 1ère valeur pour les préfixes (c'est-à-dire M. Mme Mme Dr. Dr.) ... Si oui, supprimez-le d'autres déplacez-vous à la suivante. P> LI>
comparer la 1ère valeur pour la longueur. S'il s'agit d'un seul caractère, combiner 2 premiers articles dans le tableau. P> li> ol>
Ce n'est toujours pas imbécile preuve; Cependant, il devrait aborder au moins 80% de vos affaires. p>
J'espère que cela aide. P>
Je serais d'accord avec cela, si vous pouvez casser les données dans divers ensembles de données analysés de manière fiable, vous constaterez peut-être que les «cas de problèmes» restants sont suffisamment petits pour avoir une poignée humaine.
James - merci pour vos idées très pratiques. Étant donné que les données sont généralement assez bonnes, je pense que cela devrait traiter ~ 95% des cas.
Si vous n'avez que quelques utilisateurs (<100K), voyez-vous que si vous pouvez demander à quelqu'un de le faire manuellement et utilisez votre temps sur quelque chose en valable. Puisque c'est un travail unique, le Roi naît: -) p>
Il y a environ 10k utilisateurs, donc vous avez probablement raison - c'est la contrainte du programmeur irrationnel de passer 5 heures à essayer de résoudre la moitié des cas de bord qui prendraient une heure de nettoyage «manuel» par un stagiaire.
exactement ;-) je ne le sais que trop bien
La chose la plus rapide à faire est une algorithme hybride-approche humaine. Vous ne voulez pas dépenser le temps de mettre en place un système qui fonctionne 99,99% du temps car les 5 à 10% d'optimisation vous tueront. En outre, vous ne voulez pas simplement jeter tous les travaux sur une personne, car la plupart des cas (je devine) sont assez simples. P>
Construisez-la rapidement quelque chose comme ce que les jamaïgeurs suggèrent, mais attrapez tous les cas qui semblent inhabituels ou ne correspondent pas à vos conversions prédéfinies. Ensuite, passez simplement à travers ces cas manuellement (cela ne devrait pas être trop nombreux). P>
Vous pouvez suivre ces cas par vous-même ou les sous-traiter vers d'autres utilisateurs en installant des hits en turk mécanique: p>
http://aws.amazon.com/mturk/ p>
(en supposant 500 cas à 0,05 $ (récompense élevée) Votre coût total devrait être de 25 $ au plus) P>
J'ai creusé une très simple (80% probablement) regex j'avais à Perl et ajouté des noms de groupe C # heureux C #: P>
Je poste en tant que wiki, alors quiconque n'hésitez pas à ajouter des choses qu'ils pensent aider! P> (?
Merci Mike, je verrai comment ça se passe sur mes données.
Comme les autres ont souligné, il n'y a pas de solution qui fonctionne dans tous les cas. Une des raisons pour cela est qu'il existe des noms qui peuvent être utilisés comme nom de famille d'abord et un nom de famille. P>
Vous pouvez utiliser une base de données Pour une base de données gratuite de prénoms, voir Cette réponse . P>
Si votre univers de données est <10k Noms et son offre une seule fois, mettez l'un des scénarios fractionnés décrits par d'autres affiches dans un fichier intermédiaire, passez à travers manuellement et regardez et mettez à jour le cas échéant (vous êtes surpris de la mise à jour. temps il faut pour les noms VET 10K). Cela vous prendra moins de temps que d'essayer de trouver et de construire l'algorithme parfaitement mis en œuvre. Une fois votre univers de noms> 100K, il convient de tenter de programmer votre sortie et de faire tourner un fichier pour examen manuel et modification de tous les noms qui ne vous donnent pas de prénom parfait, dernière nom. P>
static void CheckSuffix(ref string[] sArrName)
{
// Initialize suffixes
List<string> Suffixes = new List<string>();
Suffixes.Add("jr");
Suffixes.Add("sr");
Suffixes.Add("esq");
Suffixes.Add("ii");
Suffixes.Add("iii");
Suffixes.Add("iv");
Suffixes.Add("v");
Suffixes.Add("2nd");
Suffixes.Add("3rd");
Suffixes.Add("4th");
Suffixes.Add("5th");
int i = 0;
string suffix = string.Empty;
foreach (string s in sArrName)
{
string[] schk = s.ToLower().Split(new char[] { ' ' });
foreach (string sverifiy in schk)
{
if (Suffixes.Contains(sverifiy))
{
suffix = sverifiy;
sArrName[i] = sArrName[i].Replace(sverifiy.ToUpper(), string.Empty).Trim();
};
}
i += 1;
}
sArrName[2] = string.Format("{0}{1}", sArrName[2], (!string.IsNullOrEmpty(suffix) ? " " + suffix.ToUpper() + "." : string.Empty));
}
public static string[] ExtractFullname(string name)
{
string[] sArr = { "", "", ""};
string[] sName = name.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);
int chkinitial = -1;
for (int i = 0; i < sName.Length; i++)
{
if (sName[i].Length == 1) chkinitial = i;
}
switch (sName.Length)
{
case 1:
sArr[0] = name;
break;
case 2:
{
int idx = name.IndexOf(',');
if (idx != -1 && idx < name.Length) { sArr[0] = sName[1]; sArr[2] = sName[0]; } /* last, first */
else
{
idx = name.IndexOf(' ');
if (idx != -1 && idx < name.Length) { sArr[0] = sName[0]; sArr[2] = sName[1]; } /* first last */
}
}
break;
case 3:
if (chkinitial == 1) { sArr[0] = sName[0]; sArr[1] = sName[1]; sArr[2] = sName[2]; } /* first middle last */
else if (chkinitial == 2) { sArr[0] = sName[1]; sArr[1] = sName[2]; sArr[2] = sName[0]; } /* last first middle */
else if (chkinitial == -1) {
int idx = name.IndexOf(',');
if (idx != -1)
{
if (idx == (sName[0].Length + sName[1].Length + 1))
{
sArr[0] = sName[2]; sArr[2] = string.Format("{0} {1}", sName);
}
else
{
sArr[0] = string.Format("{1} {2}", sName); sArr[2] = sName[0];
}
}
else
{
sArr[0] = name;
}
}
break;
case 4:
if (chkinitial == 1) { sArr[0] = sName[0]; sArr[1] = sName[1]; sArr[2] = string.Format("{2} {3}", sName); } /* first middle last */
else if (chkinitial == 2) { sArr[0] = string.Format("{0} {1}", sName); sArr[1] = sName[2]; sArr[2] = sName[3]; } /* last first middle */
else if (chkinitial == 3) {
int idx = name.IndexOf(',');
if (idx != -1)
{
if (idx == (sName[0].Length + sName[1].Length + 1))
{
sArr[0] = sName[2]; sArr[1] = sName[3]; sArr[2] = string.Format("{0} {1}", sName);
}
else
{
sArr[0] = string.Format("{1} {2}", sName); sArr[1] = sName[3]; sArr[2] = sName[0];
}
}
else
{
sArr[0] = name;
}
}
else if (chkinitial == -1)
{
int idx = name.IndexOf(',');
if (idx != -1)
{
if (idx == (sName[0].Length))
{
sArr[0] = string.Format("{1} {2} {3}", sName); sArr[2] = sName[0];
}
else if (idx == (sName[0].Length + sName[1].Length + 1))
{
sArr[0] = string.Format("{2} {3}", sName); sArr[2] = string.Format("{0} {1}", sName);
}
else if (idx == (sName[0].Length + sName[1].Length + sName[2].Length + 1))
{
sArr[0] = sName[3]; sArr[2] = string.Format("{0} {1} {2}", sName);
}
else
{
sArr[0] = name;
}
}
else
{
sArr[0] = name;
}
}
break;
default:
/* more than 3 item in array */
sArr[0] = name;
break;
}
CheckSuffix(ref sArr);
return sArr;
}
Combien de noms avez-vous dans la base de données?
Environ 10k, il est donc toujours pratique de vérifier manuellement avec une solution qui gère 95% des cas. L'utilisation des premiers et derniers mots gèlèrent environ 85% des noms.