32 votes

Un moyen simple d'analyser le nom d'une personne en ses éléments constitutifs ?

De nombreux programmes de gestion des contacts procèdent de la sorte : vous tapez un nom ( par exemple , "John W. Smith") et il le décompose automatiquement en interne en :

Prénom : John
Second prénom : W.
Nom de famille : Smith

De même, il calcule correctement des choses comme "Mme Jane W. Smith" et "Dr. John Doe, Jr." (en supposant que vous autorisiez des champs comme "préfixe" et "suffixe" dans les noms).

Je suppose que c'est une chose assez commune que les gens voudraient faire... alors la question est... comment le feriez-vous ? Y a-t-il un simple algorithme pour cela ? Peut-être une expression régulière ?

Je recherche une solution .NET, mais je ne suis pas difficile.

Mise à jour : Je suis conscient qu'il n'existe pas de solution simple qui couvre TOUS les cas limites et toutes les cultures... mais disons, pour les besoins de l'argumentation, que vous avez besoin du nom en morceaux (remplir des formulaires - comme, par exemple, les formulaires fiscaux ou autres formulaires gouvernementaux - est un cas où vous êtes obligé de saisir le nom dans des champs fixes, que vous le vouliez ou non), mais vous ne voulez pas nécessairement forcer l'utilisateur à saisir son nom dans des champs distincts (moins de frappe = plus facile pour les utilisateurs novices).

Vous voudriez que le programme "devine" (du mieux qu'il peut) ce qui est premier, milieu, dernier, etc. Si vous le pouvez, regardez comment Microsoft Outlook fait cela pour les contacts - il vous laisse taper le nom, mais si vous avez besoin de clarifier, il y a une petite fenêtre supplémentaire que vous pouvez ouvrir. Je ferais la même chose - donner à l'utilisateur la fenêtre au cas où il voudrait saisir le nom en plusieurs morceaux - mais permettre de saisir le nom dans une case et faire une "meilleure estimation" qui couvre le plus noms communs.

1 votes

Il s'agit d'un de ces problèmes qui semblent simples, mais qui deviennent terriblement complexes dans certains cas (personnes ayant : deux seconds prénoms, des noms de famille avec un trait d'union, des préfixes comme "von", des noms asiatiques avec le nom de famille en premier, etc.)

1 votes

N'oubliez pas le cas où vous avez Madonna ou Prince comme contacts :)

0 votes

En fait, les noms de célibataires sont un plus gros problème que certaines pop stars égocentriques. Dans certains pays (l'Indonésie, par exemple), une part importante de la population n'a qu'un seul nom.

34voto

shadit Points 1975

Si vous doit faire cette analyse, je suis sûr que vous obtiendrez beaucoup de bonnes suggestions ici.

Ma suggestion est - ne pas faire cette analyse syntaxique .

Créez plutôt vos champs de saisie de manière à ce que les informations soient déjà séparées. Ayez des champs séparés pour le titre, le prénom, l'initiale du second prénom, le nom de famille, le suffixe, etc.

0 votes

"...créez vos champs de saisie de façon à ce que les informations soient déjà séparées." C'est vrai. Je suppose que c'est la meilleure pratique pour ce genre de choses. C'est aussi vrai pour le champ "Adresse"

2 votes

Qu'en est-il des personnes qui n'ont qu'un seul nom ? Les personnes dont le prénom est le nom de l'adresse officielle (Japon, Chine, Corée) ? À tout le moins, il vaut mieux ne pas s'adresser à "Mausam" en disant "Cher Mausam [NULL]...".

0 votes

Je suis d'accord. J'ai repris une ancienne application et je suis obligé d'analyser les noms parce qu'ils sont tous stockés ensemble. C'est pénible et je dois toujours ajouter une logique supplémentaire à la routine pour tenir compte d'une valeur aberrante. L'entrée de l'utilisateur varie, bien sûr, donc c'est en grande partie une question de hasard.

18voto

eselk Points 1796

Je sais que c'est vieux et qu'il y a peut-être des réponses quelque part que je n'ai pas trouvées, mais comme je n'ai rien trouvé qui fonctionne pour moi, voici ce que j'ai trouvé qui, je pense, fonctionne beaucoup comme Google Contacts et Microsoft Outlook. Il ne gère pas bien les cas limites, mais pour une bonne application de type CRM, on peut toujours demander à l'utilisateur de les résoudre (dans mon application, j'ai en fait des champs séparés tout le temps, mais j'en ai besoin pour importer des données d'une autre application qui n'a qu'un seul champ) :

    public static void ParseName(this string s, out string prefix, out string first, out string middle, out string last, out string suffix)
    {
        prefix = "";
        first = "";
        middle = "";
        last = "";
        suffix = "";

        // Split on period, commas or spaces, but don't remove from results.
        List<string> parts = Regex.Split(s, @"(?<=[., ])").ToList();

        // Remove any empty parts
        for (int x = parts.Count - 1; x >= 0; x--)
            if (parts[x].Trim() == "")
                parts.RemoveAt(x);

        if (parts.Count > 0)
        {
            // Might want to add more to this list
            string[] prefixes = { "mr", "mrs", "ms", "dr", "miss", "sir", "madam", "mayor", "president" };

            // If first part is a prefix, set prefix and remove part
            string normalizedPart = parts.First().Replace(".", "").Replace(",", "").Trim().ToLower();
            if (prefixes.Contains(normalizedPart))
            {
                prefix = parts[0].Trim();
                parts.RemoveAt(0);
            }
        }

        if (parts.Count > 0)
        {
            // Might want to add more to this list, or use code/regex for roman-numeral detection
            string[] suffixes = { "jr", "sr", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix", "x", "xi", "xii", "xiii", "xiv", "xv" };

            // If last part is a suffix, set suffix and remove part
            string normalizedPart = parts.Last().Replace(".", "").Replace(",", "").Trim().ToLower();
            if (suffixes.Contains(normalizedPart))
            {
                suffix = parts.Last().Replace(",", "").Trim();
                parts.RemoveAt(parts.Count - 1);
            }
        }

        // Done, if no more parts
        if (parts.Count == 0)
            return;

        // If only one part left...
        if (parts.Count == 1)
        {
            // If no prefix, assume first name, otherwise last
            // i.e.- "Dr Jones", "Ms Jones" -- likely to be last
            if(prefix == "")
                first = parts.First().Replace(",", "").Trim();
            else
                last = parts.First().Replace(",", "").Trim();
        }

        // If first part ends with a comma, assume format:
        //   Last, First [...First...]
        else if (parts.First().EndsWith(","))
        {
            last = parts.First().Replace(",", "").Trim();
            for (int x = 1; x < parts.Count; x++)
                first += parts[x].Replace(",", "").Trim() + " ";
            first = first.Trim();
        }

        // Otherwise assume format:
        // First [...Middle...] Last

        else
        {
            first = parts.First().Replace(",", "").Trim();
            last = parts.Last().Replace(",", "").Trim();
            for (int x = 1; x < parts.Count - 1; x++)
                middle += parts[x].Replace(",", "").Trim() + " ";
            middle = middle.Trim();
        }
    }

Désolé que le code soit long et moche, je n'ai pas encore eu le temps de le nettoyer. C'est une extension C#, donc vous l'utiliserez comme :

string name = "Miss Jessica Dark-Angel Alba";
string prefix, first, middle, last, suffix;
name.ParseName(out prefix, out first, out middle, out last, out suffix);

0 votes

C'est un peu plus gentil que ce que j'essaie de faire. J'ai trouvé cet article de blog utile pour déterminer les préfixes que je dois prendre en charge : notes.ericwillis.com/2009/11/

2 votes

L'utilisation d'un grand nombre de paramètres n'est PAS une bonne chose. Vous devriez plutôt créer un type de retour avec les parties qui s'y trouvent.

0 votes

J'aime ce que vous avez fait ici, et je l'ai repris et fait beaucoup de changements pour gérer des choses comme les noms de famille à plusieurs mots (par exemple "van Winkle"), ou les seconds prénoms multiples (par exemple "John Nathan Edward dos Santos"). Je le publie ci-dessous.

13voto

Stephen Deken Points 2418

Il n'y a pas de solution simple pour cela. La construction du nom varie d'une culture à l'autre et même dans le monde anglophone, il y a des préfixes et des suffixes qui ne font pas nécessairement partie du nom.

Une approche de base consiste à rechercher les titres honorifiques au début de la chaîne (par exemple, "Hon. John Doe") et les numéros ou d'autres chaînes à la fin (par exemple, "John Doe IV", "John Doe Jr."), mais tout ce que vous pouvez faire est d'appliquer un ensemble d'heuristiques et d'espérer le meilleur.

Il pourrait être utile de trouver une liste de noms non traités et de tester votre algorithme par rapport à cette liste. Je ne sais pas s'il y a quelque chose de préemballé là-bas, cependant.

0 votes

La réponse de Shad est plus correcte lorsqu'il s'agit de fabriquer des systèmes réels.

0 votes

Oui, j'espère que tu as une grande tolérance pour les erreurs qu'il fera inévitablement.

5voto

Vincent McNabb Points 5747

Vous n'avez probablement pas besoin de faire quoi que ce soit d'extraordinaire. Quelque chose comme ceci devrait fonctionner.

    Name = Name.Trim();

    arrNames = Name.Split(' ');

    if (arrNames.Length > 0) {
        GivenName = arrNames[0];
    }
    if (arrNames.Length > 1) {
        FamilyName = arrNames[arrNames.Length - 1];
    }
    if (arrNames.Length > 2) {
        MiddleName = string.Join(" ", arrNames, 1, arrNames.Length - 2);
    }

Vous pouvez également commencer par vérifier les titres.

0 votes

Si la conception exige que cette analyse syntaxique ait lieu, je suis d'accord pour dire que c'est un bon type d'approche.

0 votes

Il y a un petit problème avec le code ci-dessus. La vérification de la longueur devrait être faite en utilisant le tableau arrNames et non la variable Name. Vous pourriez également découper et diviser en un seul appel. Je suis d'accord que pour la plupart des scénarios, cette approche simple fonctionnera.

2 votes

Cela ne fonctionnera pas pour les noms au format "McNabb, Vincent".

4voto

Corey Trager Points 11334

Je devais le faire. En fait, quelque chose de beaucoup plus difficile que cela, car parfois le "nom" était "Smith, John" ou "Smith John" au lieu de "John Smith", ou pas du tout le nom d'une personne mais plutôt le nom d'une société. Et il fallait que cela se fasse automatiquement, sans que l'utilisateur ait la possibilité de le corriger.

Ce que j'ai fini par faire, c'est une liste limitée de modèles dans lesquels le nom peut être utilisé, comme.. :
Nom, Prénom Moyen-Initiale
Premier Dernier
Prénom Milieu-Initiale Nom
Nom, Prénom Moyen
Prénom Moyen Nom
Premier Dernier

Mettez vos M. et M. Jr. là aussi. Disons que vous vous retrouvez avec une douzaine de modèles.

Mon application disposait d'un dictionnaire de prénoms communs, de noms de famille communs (que l'on peut trouver sur le web), de titres communs, de suffixes communs (jr, sr, md) et, à l'aide de ce dictionnaire, j'étais capable de faire de très bonnes suppositions sur les modèles. Je ne suis pas si intelligent, ma logique n'était pas si sophistiquée, et pourtant, il n'était pas si difficile de créer une logique qui donnait des réponses correctes plus de 99% du temps.

4 votes

C'est agréable de voir des réponses concrètes ici, et non pas des "ne le faites pas". Google (Contacts) et Microsoft (Outlook) le font tous deux, pour les mêmes raisons que le PO. Ils ont "établi la norme", alors peu importe que la conception soit bonne ou non, le reste d'entre nous, les moutons, doit suivre si nous voulons être compétitifs. Les utilisateurs veulent des produits élégants et cool plus que des produits qui fonctionnent 100% du temps. Blâmez les grands, ou les utilisateurs, mais ne dites pas simplement "ne le faites pas".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X