Простой способ разобрать имя человека на составные части? - PullRequest
30 голосов
/ 19 сентября 2008

Многие программы управления контактами делают это - вы вводите имя (, например, , "Джон В. Смит"), и оно автоматически разбивает его на:

Имя: Джон
Отчество: З.
Фамилия: Смит

Точно так же выясняются такие вещи, как «Миссис Джейн В. Смит» и «Доктор Джон Доу-младший». также правильно (при условии, что вы допускаете поля типа «префикс» и «суффикс» в именах).

Я предполагаю, что это довольно распространенные вещи, которые люди хотели бы делать ... поэтому вопрос ... как бы вы это сделали? Есть ли простой алгоритм для этого? Может быть, регулярное выражение?

Я за решением .NET, но я не придирчив.

Обновление: Я ценю, что не существует простого решения для этого, которое охватывало бы ВСЕ крайние случаи и культуры ... но, скажем, ради аргумента, что вам нужно имя по частям (заполнение форм - как, скажем, в налоговых или других государственных формах - это один случай, когда вы обязаны ввести имя в фиксированные поля, нравится вам это или нет), но вы не обязательно заставляете пользователя вводить свое имя в дискретные поля (меньше ввода = легче для начинающих пользователей).

Вы бы хотели, чтобы программа «угадала» (насколько это возможно), что будет первым, средним, последним и т. Д. Если вы можете, посмотрите, как Microsoft Outlook делает это для контактов - она ​​позволяет вам ввести имя, но если вам нужно уточнить, есть дополнительное маленькое окно, которое вы можете открыть. Я бы сделал то же самое - предоставил бы пользователю окно на тот случай, если он захочет ввести имя в виде отдельных частей, - но при этом можно будет ввести имя в одном поле и сделать «наилучшее предположение», охватывающее большинство общие имена.

Ответы [ 22 ]

32 голосов
/ 19 сентября 2008

Если вы должны выполнить этот анализ, я уверен, что вы получите много хороших предложений здесь.

Мое предложение - не делайте этого анализа .

Вместо этого создайте поля ввода так, чтобы информация уже была выделена. Имеют отдельные поля для заголовка, имени, отчества, фамилии, суффикса и т. Д.

17 голосов
/ 26 апреля 2013

Я знаю, что это старый и может быть ответы где-то, что я не мог найти уже, но так как я не мог найти ничего, что работает для меня, это то, что я придумал, я думаю, что работает так же, как Google Contacts Microsoft Outlook. Он плохо обрабатывает крайние случаи, но для хорошего приложения типа CRM пользователя всегда можно попросить разрешить их (в моем приложении у меня все время есть отдельные поля, но мне это нужно для импорта данных из другого приложения, которое имеет только одно поле):

    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();
        }
    }

Извините, что код длинный и уродливый, я не удосужился его почистить. Это расширение C #, поэтому вы можете использовать его следующим образом:

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);
10 голосов
/ 19 сентября 2008

Простого решения для этого не существует. Конструкция имени варьируется от культуры к культуре, и даже в англоязычном мире есть префиксы и суффиксы, которые не обязательно являются частью имени.

Основной подход заключается в поиске honififics в начале строки (например, "Hon. John Doe") и чисел или некоторых других строк в конце (например, "John Doe IV", "John Doe Jr. "), но на самом деле все, что вы можете сделать, это применить набор эвристик и надеяться на лучшее.

Может быть полезно найти список необработанных имен и проверить ваш алгоритм на его соответствие. Я не знаю, что там есть что-нибудь заранее упакованное.

5 голосов
/ 19 сентября 2008

Вам, вероятно, не нужно делать что-то необычное на самом деле. Нечто подобное должно работать.

    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);
    }

Вы также можете сначала проверить заголовки.

4 голосов
/ 20 сентября 2008

Я должен был сделать это. На самом деле, что-то гораздо сложнее, чем это, потому что иногда «имя» будет «Смит, Джон» или «Смит Джон» вместо «Джон Смит», или вообще не имя человека, а название компании. И он должен был сделать это автоматически без возможности для пользователя исправить это.

Я закончил тем, что придумал конечный список шаблонов, в которых могло бы быть имя, например:
Последний, первый средний инициал
Первый Последний
Первый средний начальный последний
Последняя, ​​первая средняя
Первый Средний Последний
Первый Последний

Добавьте сюда свою миссис Джуниор. Допустим, вы получили около дюжины шаблонов.

Мое приложение имело словарь общих имен, общих фамилий (вы можете найти их в Интернете), общие заголовки, общие суффиксы (jr, sr, md) и использование, которое могло бы дать действительно хорошие догадки о шаблоны. Я не такой умный, моя логика не была такой причудливой, и все же, было не так сложно создать какую-то логику, которая угадывалась более чем в 99% случаев.

3 голосов
/ 12 декабря 2018

Придя к этому разговору с 10-летним опозданием, но все еще ища элегантное решение, я прочитал эту ветку и решил пойти по пути, который выбрал @eselk, но подробно остановился на нем:

public class FullNameDTO
{
    public string Prefix     { get; set; }
    public string FirstName  { get; set; }
    public string MiddleName { get; set; }
    public string LastName   { get; set; }
    public string Suffix     { get; set; }
}

public static class FullName
{
    public static FullNameDTO GetFullNameDto(string fullName)
    {
        string[] knownPrefixes    = { "mr", "mrs", "ms", "miss", "dr", "sir", "madam", "master", "fr", "rev", "atty", "hon", "prof", "pres", "vp", "gov", "ofc" };
        string[] knownSuffixes    = { "jr", "sr", "ii", "iii", "iv", "v", "esq", "cpa", "dc", "dds", "vm", "jd", "md", "phd" };
        string[] lastNamePrefixes = { "da", "de", "del", "dos", "el", "la", "st", "van", "von" };

        var prefix     = string.Empty;
        var firstName  = string.Empty;
        var middleName = string.Empty;
        var lastName   = string.Empty;
        var suffix     = string.Empty;

        var fullNameDto = new FullNameDTO
        {
            Prefix     = prefix,
            FirstName  = firstName,
            MiddleName = middleName,
            LastName   = lastName,
            Suffix     = suffix
        };

        // Split on period, commas or spaces, but don't remove from results.
        var namePartsList = Regex.Split(fullName, "(?<=[., ])").ToList();

        #region Clean out the crap.
        for (var x = namePartsList.Count - 1; x >= 0; x--)
        {
            if (namePartsList[x].Trim() == string.Empty)
            {
                namePartsList.RemoveAt(x);
            }
        }
        #endregion

        #region Trim all of the parts in the list
        for (var x = namePartsList.Count - 1; x >= 0; x--)
        {
            namePartsList[x] = namePartsList[x].Trim();
        }
        #endregion

        #region Only one Name Part - assume a name like "Cher"
        if (namePartsList.Count == 1)
        {
            firstName = namePartsList.First().Replace(",", string.Empty).Trim();
            fullNameDto.FirstName = firstName;

            namePartsList.RemoveAt(0);
        }
        #endregion

        #region Get the Prefix
        if (namePartsList.Count > 0)
        {
            //If we find a prefix, save it and drop it from the overall parts
            var cleanedPart = namePartsList.First()
                                           .Replace(".", string.Empty)
                                           .Replace(",", string.Empty)
                                           .Trim()
                                           .ToLower();

            if (knownPrefixes.Contains(cleanedPart))
            {
                prefix = namePartsList[0].Trim();
                fullNameDto.Prefix = prefix;

                namePartsList.RemoveAt(0);
            }
        }
        #endregion

        #region Get the Suffix
        if (namePartsList.Count > 0)
        {
            #region Scan the full parts list for a potential Suffix
            foreach (var namePart in namePartsList)
            {
                var cleanedPart = namePart.Replace(",", string.Empty)
                                          .Trim()
                                          .ToLower();

                if (!knownSuffixes.Contains(cleanedPart.Replace(".", string.Empty))) { continue; }

                if (namePart.ToLower() == "jr" && namePart != namePartsList.Last()) { continue; }

                suffix             = namePart.Replace(",", string.Empty).Trim();
                fullNameDto.Suffix = suffix;

                namePartsList.Remove(namePart);
                break;
            }
            #endregion
        }
        #endregion

        //If, strangely, there's nothing else in the overall parts... we're done here.
        if (namePartsList.Count == 0) { return fullNameDto; }

        #region Prefix/Suffix taken care of - only one "part" left.
        if (namePartsList.Count == 1)
        {
            //If no prefix, assume first name (e.g. "Cher"), otherwise last (e.g. "Dr Jones", "Ms Jones")
            if (prefix == string.Empty)
            {
                firstName = namePartsList.First().Replace(",", string.Empty).Trim();
                fullNameDto.FirstName = firstName;
            }
            else
            {
                lastName = namePartsList.First().Replace(",", string.Empty).Trim();
                fullNameDto.LastName = lastName;
            }
        }
        #endregion

        #region First part ends with a comma
        else if (namePartsList.First().EndsWith(",") || (namePartsList.Count >= 3 && namePartsList.Any(n => n == ",") && namePartsList.Last() != ","))
        {
            #region Assume format: "Last, First"
            if (namePartsList.First().EndsWith(","))
            {
                lastName             = namePartsList.First().Replace(",", string.Empty).Trim();
                fullNameDto.LastName = lastName;
                namePartsList.Remove(namePartsList.First());

                firstName             = namePartsList.First();
                fullNameDto.FirstName = firstName;
                namePartsList.Remove(namePartsList.First());

                if (!namePartsList.Any()) { return fullNameDto; }

                foreach (var namePart in namePartsList)
                {
                    middleName += namePart.Trim() + " ";
                }
                fullNameDto.MiddleName = middleName;

                return fullNameDto;
            }
            #endregion

            #region Assume strange scenario like "Last Suffix, First"
            var indexOfComma = namePartsList.IndexOf(",");

            #region Last Name is the first thing in the list
            if (indexOfComma == 1)
            {
                namePartsList.Remove(namePartsList[indexOfComma]);

                lastName             = namePartsList.First().Replace(",", string.Empty).Trim();
                fullNameDto.LastName = lastName;
                namePartsList.Remove(namePartsList.First());

                firstName             = namePartsList.First();
                fullNameDto.FirstName = firstName;
                namePartsList.Remove(namePartsList.First());

                if (!namePartsList.Any()) { return fullNameDto; }

                foreach (var namePart in namePartsList)
                {
                    middleName += namePart.Trim() + " ";
                }
                fullNameDto.MiddleName = middleName;

                return fullNameDto;
            }
            #endregion

            #region Last Name might be a prefixed one, like "da Vinci"
            if (indexOfComma == 2)
            {
                var possibleLastPrefix = namePartsList.First()
                                                      .Replace(".", string.Empty)
                                                      .Replace(",", string.Empty)
                                                      .Trim()
                                                      .ToLower();

                if (lastNamePrefixes.Contains(possibleLastPrefix))
                {
                    namePartsList.Remove(namePartsList[indexOfComma]);

                    var lastPrefix = namePartsList.First().Trim();
                    namePartsList.Remove(lastPrefix);

                    lastName             = $"{lastPrefix} {namePartsList.First().Replace(",", string.Empty).Trim()}";
                    fullNameDto.LastName = lastName;
                    namePartsList.Remove(namePartsList.First());
                }
                else
                {
                    lastName = namePartsList.First().Replace(",", string.Empty).Trim();
                    namePartsList.Remove(namePartsList.First());

                    lastName = lastName + " " + namePartsList.First().Replace(",", string.Empty).Trim();
                    namePartsList.Remove(namePartsList.First());

                    fullNameDto.LastName = lastName;
                }

                namePartsList.Remove(",");

                firstName             = namePartsList.First();
                fullNameDto.FirstName = firstName;
                namePartsList.Remove(namePartsList.First());

                if (!namePartsList.Any()) { return fullNameDto; }

                foreach (var namePart in namePartsList)
                {
                    middleName += namePart.Trim() + " ";
                }
                fullNameDto.MiddleName = middleName;

                return fullNameDto;
            }
            #endregion
            #endregion
        }
        #endregion

        #region Everything else
        else
        {
            if (namePartsList.Count >= 3)
            {
                firstName = namePartsList.First().Replace(",", string.Empty).Trim();
                fullNameDto.FirstName = firstName;
                namePartsList.RemoveAt(0);

                //Check for possible last name prefix

                var possibleLastPrefix = namePartsList[namePartsList.Count - 2]
                                               .Replace(".", string.Empty)
                                               .Replace(",", string.Empty)
                                               .Trim()
                                               .ToLower();

                if (lastNamePrefixes.Contains(possibleLastPrefix))
                {
                    lastName = $"{namePartsList[namePartsList.Count - 2].Trim()} {namePartsList[namePartsList.Count -1].Replace(",", string.Empty).Trim()}";
                    fullNameDto.LastName = lastName;

                    namePartsList.RemoveAt(namePartsList.Count - 1);
                    namePartsList.RemoveAt(namePartsList.Count - 1);
                }
                else
                {
                    lastName = namePartsList.Last().Replace(",", string.Empty).Trim();
                    fullNameDto.LastName = lastName;

                    namePartsList.RemoveAt(namePartsList.Count - 1);
                }

                middleName = string.Join(" ", namePartsList).Trim();
                fullNameDto.MiddleName = middleName;

                namePartsList.Clear();
            }
            else
            {
                if (namePartsList.Count == 1)
                {
                    lastName = namePartsList.First().Replace(",", string.Empty).Trim();
                    fullNameDto.LastName = lastName;

                    namePartsList.RemoveAt(0);
                }
                else
                {
                    var possibleLastPrefix = namePartsList.First()
                                             .Replace(".", string.Empty)
                                             .Replace(",", string.Empty)
                                             .Trim()
                                             .ToLower();

                    if (lastNamePrefixes.Contains(possibleLastPrefix))
                    {
                        lastName = $"{namePartsList.First().Replace(",", string.Empty).Trim()} {namePartsList.Last().Replace(",", string.Empty).Trim()}";
                        fullNameDto.LastName = lastName;

                        namePartsList.Clear();
                    }
                    else
                    {
                        firstName = namePartsList.First().Replace(",", string.Empty).Trim();
                        fullNameDto.FirstName = firstName;

                        namePartsList.RemoveAt(0);

                        lastName = namePartsList.Last().Replace(",", string.Empty).Trim();
                        fullNameDto.LastName = lastName;

                        namePartsList.Clear();
                    }
                }
            }
        }
        #endregion

        namePartsList.Clear();

        fullNameDto.Prefix     = prefix;
        fullNameDto.FirstName  = firstName;
        fullNameDto.MiddleName = middleName;
        fullNameDto.LastName   = lastName;
        fullNameDto.Suffix     = suffix;

        return fullNameDto;
    }
}

Это будет обрабатывать несколько различных сценариев, и я написал (пока) более 50 различных юнит-тестов, чтобы убедиться в этом.

Снова обращайтесь к @eselk за его идеями, которые помогли мне написать расширенную версию его превосходного решения. И, в качестве бонуса, это также обрабатывает странный случай человека по имени "JR".

3 голосов
/ 27 декабря 2008

Понимая, что это плохая идея, я написал это регулярное выражение на Perl - вот что мне помогло. Я уже отфильтровал названия компаний.
Вывод в формате vcard: (hon_prefix, имя_имя, дополнительное_имя, имя_семейства, суффикс hon.)

/^ \s*
    (?:((?:Dr.)|(?:Mr.)|(?:Mr?s.)|(?:Miss)|(?:2nd\sLt.)|(?:Sen\.?))\s+)? # prefix
    ((?:\w+)|(?:\w\.)) # first name
(?: \s+ ((?:\w\.?)|(?:\w\w+)) )?  # middle initial
(?: \s+ ((?:[OD]['’]\s?)?[-\w]+))    # last name
(?: ,? \s+ ( (?:[JS]r\.?) | (?:Esq\.?) | (?: (?:M)|(?:Ph)|(?:Ed) \.?\s*D\.?) | 
         (?: R\.?N\.?) | (?: I+) )  )? # suffix
\s* $/x

примечания:

  • не обрабатывает IV, V, VI
  • Жестко закодированные списки префиксов, суффиксов. эволюционировал из набора данных ~ 2K имен
  • Не обрабатывает несколько суффиксов (например, MD, PhD)
  • Предназначен для американских имен - не будет работать должным образом на латинизированных японских именах или других системах именования
3 голосов
/ 19 сентября 2008

Я ценю, что это трудно сделать правильно - но если вы предоставите пользователю способ редактировать результаты (скажем, всплывающее окно для редактирования имени, если оно не угадано) ) и до сих пор предполагаю «правильно» в большинстве случаев ... конечно, это сложное предположение.

Легко сказать "не делай этого", рассматривая проблему теоретически, но иногда обстоятельства диктуют иное. Наличие полей для всех частей имени (название, первая, средняя, ​​последняя, ​​суффикс и другие) может занять много места на экране - и в сочетании с проблемой адреса (тема для другого дня) ) может действительно загромождать то, что должно быть чистым, простым пользовательским интерфейсом.

Я полагаю, что ответом должно быть «не делайте этого, если вам это абсолютно не нужно, и если вы это сделаете, сделайте это простым (некоторые методы для этого были опубликованы здесь) и предоставьте пользователю средства для редактирования результатов, если» необходимо. "

2 голосов
/ 01 марта 2012

Реальное решение здесь не отвечает на вопрос. Знамение информации должно быть соблюдено. Имя это не просто имя; это то, как нас знают.

Проблема в том, что мы не знаем точно, какие части помечены и для чего они используются. Почетные префиксы должны предоставляться только в личных корреляциях; Доктор является почетным званием, которое происходит от названия. Вся информация о человеке связана с его личностью, она просто определяет, что является соответствующей информацией. Вам необходимо имя и фамилия по причинам администрации; номер телефона, адреса электронной почты, описания земель и почтовые адреса; все к знамению личности, зная, с кем ты имеешь дело.

Настоящая проблема здесь в том, что человек теряется в администрации. Внезапно, после того, как они только вводят свою личную информацию в форму и передают ее в произвольную программу для обработки, они получают все виды чести и пожеланий, выбрасываемые с помощью готового шаблона. Это не верно; Достопочтенный сэр или мадам, если личный интерес проявляется к причине соответствия, то письмо никогда не должно быть написано по шаблону. Личное соответствие требует небольшого знания о получателе. Мужчина или женщина ходили в школу, чтобы стать врачом или судьей, в какой культуре они воспитывались.

В других культурах имя состоит из переменного числа символов. Имя человека для нас может быть интерпретировано только как строка чисел, где пробелы фактически определяются шириной символа вместо символа пробела. Honorifics в этих случаях вместо одного или нескольких символов префикс и суффикс фактического имени. Вежливая вещь, которую нужно сделать, - это использовать полученную вами строку, если вы знаете, что она почетная, во что бы то ни стало, использовать ее, но это опять-таки подразумевает некоторые личные знания получателя. Называть сенсея чем-то другим, кроме сенсея, неправильно. Не в смысле логической ошибки, а в том, что вы только что оскорбили своего абонента, и теперь вы должны найти шаблон, который поможет вам извиниться.

Для целей автоматического безличного соответствия может быть разработан шаблон для таких вещей, как ежедневные статьи, еженедельные выпуски и т. Д., Но проблема становится важной, когда получатель инициирует автоматическое сопоставление.

То, что происходит, является ошибкой. Недостающая информация. Неизвестная или отсутствующая информация всегда создает исключение. Реальная проблема не в том, как разделить имя человека на отдельные компоненты с помощью выражения, а в том, как вы их называете.

Решение состоит в том, чтобы создать дополнительное поле, сделать его необязательным, если имя и фамилия уже есть, и назвать его «Как мы можем вас называть» или «Как мы будем называть вас« ». Врач и судья позаботятся о том, чтобы вы правильно их рассмотрели. Это не проблемы программирования, это проблемы общения.

Хорошо, плохой способ выразить это, но, на мой взгляд, имя пользователя, имя тега и идентификатор хуже. Итак, мое решение; пропущенный вопрос: «Как мы должны вас называть?»

Это единственное решение, когда вы можете позволить себе задать новый вопрос. Такт превалирует. Создайте новое поле на ваших пользовательских формах, назовите его «Псевдоним», пометьте для пользователя «Как мы должны вас называть?», Тогда у вас есть средства для общения. Используйте имя и фамилию, если получатель не дал псевдоним или лично знаком с отправителем, тогда имя и отчество приемлемы.

To Me, _______________________ (standard subscribed corrospondence)
To Me ( Myself | I ), ________ (standard recipient instigated corrospondence)
To Me Myself I, ______________ (look out, its your mother, and you're in big trouble;
                                nobody addresses a person by their actual full name)

Dear *(Mr./Mrs./Ms./Dr./Hon./Sen.) Me M. I *(I),
To Whom it may Concern;

В противном случае вы ищете что-то стандартное: привет, привет, вы можете быть победителем.

Если у вас есть данные, представляющие собой имя человека в одной строке, у вас нет проблем, потому что у вас уже есть его псевдоним. Если вам нужно имя и фамилия, а затем просто Left (name, instr (name, "")) & "" & Right (name, instrrev (name, "")), моя математика, вероятно, неверна, я Я немного из практики. сравните левый и правый с известными префиксами и суффиксами и исключите их из ваших совпадений. Обычно отчество редко используется, за исключением случаев подтверждения личности; какой адрес или номер телефона говорит вам намного больше. Наблюдая за переносом слов, можно определить, что если фамилия не используется, вместо нее будет одна из средних.

Для поиска в списках имен и фамилий необходимо учитывать возможность использования одного из средних; для этого потребуется четыре поиска: один для фильтрации первого и последнего, затем другой для фильтрации первого и среднего, затем другой для фильтрации среднего и последнего, а затем еще один для фильтрации среднего и среднего. В конечном счете, имя всегда является первым, а последнее всегда последним, и может быть любое количество отчеств; чем меньше, тем больше, и там, где ноль вероятен, но маловероятен.

Иногда люди предпочитают, чтобы их называли Билл, Гарри, Джим, Боб, Дуг, Бет, Сью или Мадонна; чем их настоящие имена; похожи, но нереально ожидаемы от каждого, кто осознает все различные возможности.

Самое вежливое, что ты мог сделать, это спросить; Как мы можем вам позвонить?

2 голосов
/ 25 января 2010

Есть несколько надстроек, которые мы использовали в нашей компании для достижения этой цели. Я закончил тем, что создал способ на самом деле указать форматы для имени в разных импорте для разных клиентов. Есть компания, у которой есть инструмент, который, по моему опыту, стоит своих денег и действительно невероятен при решении этой проблемы. Это по адресу: http://www.softwarecompany.com/ и прекрасно работает. Наиболее эффективный способ сделать это без использования статистического подхода - разделить строку запятыми или пробелами, а затем: 1. убрать заголовки и префиксы 2. убрать суффиксы из 3, разобрать имя в порядке (2 names = F & L, 3 имени = FML или LMF) в зависимости от порядка строки ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...