31

多くの連絡先管理プログラムがこれを行います。名前 (「John W. Smith」など) を入力すると、内部的に次のように自動的に分割されます。

名:ジョン
ミドルネーム: W.
姓:スミス

同様に、"Mrs. Jane W. Smith" や "Dr. John Doe, Jr." などを計算します。正しくも同様です(名前に「接頭辞」や「接尾辞」などのフィールドを許可すると仮定します)。

これは、人々がやりたいと思うかなり一般的なことだと思います...だから問題は...どうやってやりますか? これには簡単なアルゴリズムがありますか?もしかして正規表現?

私は .NET ソリューションを求めていますが、うるさいわけではありません。

更新:すべてのエッジケースと文化をカバーする簡単な解決策がないことを理解しています...しかし、議論のために、名前をバラバラにする必要があるとしましょう(フォームに記入する-たとえば、税金やその他のように)政府のフォーム - 好むと好まざるとにかかわらず、固定フィールドに名前を入力しなければならないケースの 1 つですが、必ずしもユーザーに個別のフィールドに名前を入力するよう強制する必要はありません (入力が少ない = より簡単です)。初心者ユーザー)。

最初、中間、最後などをプログラムに (できる限り) "推測" させたいと思うでしょう。可能であれば、Microsoft Outlook が連絡先に対してどのようにこれを行うかを見てください。名前を入力することはできますが、明確にする必要がある場合は、開くことができる特別な小さなウィンドウがあります。私は同じことをします - ユーザーが別々の部分に名前を入力したい場合に備えてウィンドウを提供します - ただし、1 つのボックスに名前を入力し、最も一般的な名前をカバーする「最良の推測」を行うことができます。

4

23 に答える 23

33

この解析を行う必要がある場合は、ここで多くの良い提案が得られると確信しています。

私の提案は、この解析を行わないことです

代わりに、情報がすでに分離されているように入力フィールドを作成してください。タイトル、ファースト ネーム、ミドル ネームのイニシャル、姓、接尾辞などに個別のフィールドを用意します。

于 2008-09-19T16:29:19.577 に答える
11

これに対する簡単な解決策はありません。 名前の構成は文化によって異なり、英語圏でも、必ずしも名前の一部ではない接頭辞と接尾辞があります。

基本的なアプローチは、文字列の最初に敬語(「Hon.John Doe」など)を探し、最後に数字またはその他の文字列(「JohnDoe IV」、「John DoeJr。」など)を探すことです。しかし、実際にできることは、一連のヒューリスティックを適用して、最高のものを期待することだけです。

未処理の名前のリストを見つけて、それに対してアルゴリズムをテストすると便利な場合があります。でも、あらかじめパッケージ化されているものがあるかどうかはわかりません。

于 2008-09-19T16:31:26.517 に答える
5

あなたはおそらく本当に特別なことをする必要はありません。このようなものが機能するはずです。

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

最初にタイトルを確認することもできます。

于 2008-09-19T16:34:15.697 に答える
4

私はこれをしなければなりませんでした。実際には、これよりもはるかに難しいのは、「名前」が「John Smith」ではなく「Smith, John」または「Smith John」になったり、人の名前ではなく会社の名前になったりすることがあるからです。また、ユーザーが修正する機会を与えずに自動的に行う必要がありました。

私が 最終的に やったのは 、
次 の ような名前が含まれる可能性のあるパターンの有限リストを考え出すことでした。




あなたのMr's、Jr'sも入れてください。1ダースほどのパターンで終わるとしましょう。

私のアプリケーションには、一般的な名、一般的な姓 (これらは Web で見つけることができます)、一般的なタイトル、一般的な接尾辞 (jr、sr、md) の辞書があり、それを使用すると、パターンについて実際に適切な推測を行うことができます。私はそれほど頭が良くなく、ロジックもそれほど凝ったものではありませんでしたが、99% 以上の確率で正しく推測するロジックを作成することはそれほど難しくありませんでした。

于 2008-09-20T02:58:13.437 に答える
3

これを理解するのは悪い考えです。私はこの正規表現をperlで書きました-これが私にとって最もうまくいったものです。私はすでに会社名を除外していました。
vcard形式で出力: (hon_prefix, given_name, additional_name, family_name, hon.suffix)

/^ \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)
  • アメリカの名前用に設計されています - ローマ字化された日本語の名前やその他の命名システムでは正しく機能しません
于 2008-12-26T21:43:02.933 に答える
3

これを正しく行うのは難しいことです、結果を編集する方法 (たとえば、正しく推測されなかった場合に名前を編集するためのポップアップ ウィンドウ) をユーザーに提供し、それでもほとんどの場合「正しい」と推測する場合ケース... もちろん、難しいのは推測です。

問題を理論的に見て「やらない」と言うのは簡単ですが、状況によってはそうでない場合もあります。名前のすべての部分 (タイトル、ファースト、ミドル、ラスト、サフィックスなど) のフィールドを用意すると、多くの画面領域を占有する可能性があり、アドレスの問題 (別の日のトピック) と組み合わせると、 ) は、クリーンでシンプルな UI であるべきものを混乱させる可能性があります。

答えは、「絶対に必要でない限り実行しないでください。実行する場合は、シンプルに保ち (これに関するいくつかの方法がここに投稿されています)、必要に応じて結果を編集する手段をユーザーに提供してください。」

于 2008-09-19T18:42:12.660 に答える
3

ここでの本当の解決策は、質問に答えません。情報の前兆を観察する必要があります。名前は単なる名前ではありません。それが私たちが知られている方法です。

ここでの問題は、どの部品が何にラベル付けされ、何に使用されるかを正確に把握していないことです。名誉ある接頭辞は、個人的な通信でのみ付与されるべきです。ドクターは肩書きから派生した敬称です。人に関するすべての情報は、そのアイデンティティに関連しています。関連情報とは何かを判断しているだけです。管理上の理由から、姓名が必要です。電話番号、電子メール アドレス、土地の説明、郵送先住所。あなたが誰を扱っているかを知って、アイデンティティの前兆にすべて。

ここでの本当の問題は、管理者が迷子になってしまうことです。フォームに個人情報を入力し、それを任意のプログラムに送信して処理しただけで、突然、既製のテンプレートから吐き出されるあらゆる種類の敬語や歓喜の言葉が与えられるようになります。これは間違っています; 殿下、個人的な関心が通信の理由に向けられている場合、手紙は決してテンプレートから書かれるべきではありません. 個人的な文通には、受信者に関する少しの知識が必要です。男性か女性か、医者か裁判官になるために学校に行ったか、どんな文化の中で育ったか。

他の文化では、名前は可変数の文字で構成されます。私たちにとっての人の名前は、スペース文字ではなく文字幅によってスペースが実際に決定される数字の文字列としてのみ解釈できます。このような場合の敬称は、代わりに、実際の名前の前に付けたり後ろに付けたりする 1 つまたは複数の文字です。礼儀正しいのは、与えられた文字列を使用することです。敬称を知っている場合は、必ずそれを使用してください。ただし、これもまた、受信者の何らかの個人的な知識を意味します。先生を先生以外と呼ぶのは間違っている。論理エラーという意味ではなく、発信者を侮辱したという意味で、謝罪するのに役立つテンプレートを見つける必要があります.

自動化された非個人的な通信を目的として、日刊紙、週刊誌などのテンプレートが考案される場合がありますが、通信が受信者によって自動化されたサービスに促された場合、問題は重要になります。

何が起こるかはエラーです。情報がありません。情報が不明または欠落している場合は、常に例外が生成されます。本当の問題は、人の名前を式で個々のコンポーネントに分離する方法ではなく、それらを何と呼ぶか​​です。

解決策は、追加のフィールドを作成し、姓名が既にある場合はオプションにして、「What may we call you」または「How should we refer you as」と呼ぶことです。医師と裁判官は、あなたがそれらに適切に対処できるようにします。これらはプログラミングの問題ではなく、コミュニケーションの問題です。

悪い言い方ですが、私の意見では、ユーザー名、タグ名、ID の方が悪いと思います。だから私の解決策; 「私たちはあなたを何と呼ぶべきですか?」という欠けている質問です。

これは、新しい質問を作成する余裕がある場合の解決策にすぎません。タクトが勝つ。ユーザーフォームに新しいフィールドを作成し、それを Alias と呼び、ユーザーに「What should we call you?」というラベルを付けると、通信する手段が得られます。受信者がエイリアスを指定していない場合、または送信者に個人的に精通している場合を除き、ファーストネームとラストネームを使用してください。

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;

それ以外の場合は、標準的なものを探しています。こんにちは、挨拶、勝者になる可能性があります。

人の名前がす​​べて 1 つの文字列になっているデータがある場合は、エイリアスが既にあるため、問題はありません。姓と名が必要な場合は、Left(name,instr(name," ")) & " " & Right(name,instrrev(name," ")) だけです。私の計算はおそらく間違っています。少し練習不足です。左と右を既知の接頭辞と接尾辞と比較し、それらを一致から除外します。一般に、身元を確認する場合を除いて、ミドルネームはめったに使用されません。住所や電話番号がより多くのことを教えてくれます。ハイフネーションを監視すると、姓が使用されていない場合は、代わりに中間の名前の 1 つが使用されることがわかります。

姓と名のリストを検索する場合は、中間の名前のいずれかが代わりに使用された可能性を考慮する必要があります。これには 4 つの検索が必要です。1 つは最初と最後をフィルタリングするためのもので、もう 1 つは最初と中間をフィルタリングするためのもので、もう 1 つは中間と最後をフィルタリングするためのもので、もう 1 つは中間と中間をフィルタリングするためのものです。最終的に、ファースト ネームは常にファースト ネームであり、ラスト ネームは常にラスト ネームであり、ミドル ネームはいくつあってもかまいません。少ないほど多く、ゼロになる可能性は高いですが、可能性は低いです。

ビル、ハリー、ジム、ボブ、ダグ、ベス、スー、マドンナと呼ばれることを好む人もいます。彼らの実際の名前よりも。似ていますが、すべての異なる可能性を理解することは非現実的に期待されています。

あなたができる最も丁寧なことは、尋ねることです。私たちはあなたを何と呼ぶことができますか?

于 2012-03-01T00:11:32.480 に答える
3

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」という名前の人物の奇妙なインスタンスも処理します。

于 2018-12-11T21:16:16.810 に答える
2

これを実現するために社内で使用したアドインがいくつかあります。最終的に、さまざまなクライアントのさまざまなインポートで名前の形式を実際に指定する方法を作成しました。私の経験では、価格に見合った価値があり、このテーマに取り組むときに本当に信じられないほど素晴らしいツールを持っている会社があります. http://www.softwarecompany.com/ にあり、うまく機能します。統計的アプローチを使用せずにこれを行う最も効率的な方法は、文字列をコンマまたはスペースで分割してから: 1. タイトルとプレフィックスを削除します 2. サフィックスを削除します 3. ( 2 名 = F & L, 3 つの名前 = FML または LMF) string() の順序によって異なります。

于 2010-01-25T20:20:26.553 に答える
1

あなたは明白なことをすることができます:接尾辞としてJr.、II、IIIなどを探し、接頭辞としてMr.、Mrs.、Dr。などを探してそれらを削除すると、最初の単語が名、最後の単語が最後になります名前、その間のすべてはミドルネームです。それ以外に、これに対する絶対確実な解決策はありません。

完璧な例は、David Lee Roth(姓:Roth)とEddie Van Halen(姓:Van Halen)です。アン・マリー・スミスの名が「アン・マリー」である場合、それをミドルネームがマリーであるアンと区別する方法はありません。

于 2008-09-19T16:31:35.750 に答える
1

単にこれを行う必要がある場合は、オプションの選択として推測を UI に追加します。このようにして、名前をどのように解析したかをユーザーに伝え、提供したリストから別の解析を選択させることができます。

于 2008-09-20T22:49:58.767 に答える
1

驚くほどうまく機能する NetGender と呼ばれるこの種のサードパーティ製ツールがあります。私はそれを使用して、予測不可能な形式で大量の実際に不正な形式の名前を解析しました。彼らのページの例を見て、ダウンロードして試すこともできます。

http://www.softwarecompany.com/dotnet/netgender.htm

これらの統計は、420 ​​万人の名前のサンプリングに基づいて作成されました。Name Parts とは、スペースで区切られた個別のパーツの数を意味します。データベース内のほとんどの名前で、非常に高い割合が正しかった。部品が上がるにつれて正確性は低下しましたが、部品が 3 つを超える名前はほとんどなく、部品が 4 つを超える名前はほとんどありませんでした。私たちの場合はこれで十分でした。ソフトウェアが失敗したのは、コンマで区切られていても、よく知られていないマルチパートの姓を認識することでした。これを解読できれば、全データの合計で間違いの数は 1% 未満でした。

Name Parts | Correct | Percent of Names in DB
 2             100%       48%
 3              98%       42%
 4              70%        9%
 5              45%        0.25%
于 2011-09-01T20:31:30.623 に答える
1

私はすでにページの読み込み時にこれをサーバー側で行っています。実際のユーザー データ (名、ミドルネーム、姓) とデータ型 (名、ミドル、ラスト) の 2 つのパラメーターが渡される Coldfusion CFC を作成しました。次に、ハイフン、アポストロフィ、スペース、およびフォーマットが適切にチェックされます。元。マクドナルド、マクマリー、オニール、ロダム クリントン、エリック フォン ダッチ、GW ブッシュ、ジャック バートン Jr.、ポール オーキン博士、クリス ディ サントス。ユーザーが名前を 1 つしか持たない場合は、名のフィールドのみが必須で、ミドル ネームとラスト ネームはオプションです。

Prefix、Suffix、Custom を除き、すべての情報は小文字で保存されます。このフォーマットは、db への保存時ではなく、ページのレンダリング時に行われます。ユーザーがデータを入力するときの検証フィルタリングがありますが。コードを投稿できません。正規表現の使用を開始しましたが、すべてのシナリオで混乱しすぎて信頼できなくなりました。標準ロジック ブロック (if/else、switch/case) を使用し、読みやすくデバッグしやすくしました。すべての入力/DB フィールドを分離してください! はい、これには多少のコーディングが必要ですが、完了すると組み合わせの 99% を占めるはずです。これまでのところ英語の名前のみに基づいており、国際化は行われていません。

考慮すべき点は次のとおりです。

  • ハイペン(例:Rodham-Clinton、最初、中間、または最後にある可能性があります)
  • アポストロフィ (例: O'Neill、最初、中間、または最後にある可能性があります)
  • スペース
  • Mc と Mac (例: McDonald、MacMurray は、最初、中間、または
    最後にある可能性があります)
  • ファースト ネーム: 複数のファースト ネーム (例: Joe Bob Briggs)
  • 姓: de,di,et,der,den,van,von,af は小文字にする必要があります (例: Eric von Dander、Mary di Carlo)
  • プレフィックス: Dr.、Prof. など
  • 接尾辞: Jr.、Sr.、Esq.、II、IIIなど

ユーザーが情報を入力すると、db のフィールド スキーマは次のようになります。

  • 接頭辞/役職 (ドロップダウンを使用した博士など)
  • Prefix/Title Custom (ユーザーは、テキスト フィールドを使用してカスタムを入力できます。例: Capt.)
  • ファーストネーム
  • 真ん中
  • 苗字
  • 接尾辞 (ドロップダウンを使用した Jr.、III、Prof.、Ret. など)
  • Suffix Custom (ユーザーはカスタムを入力できます。例: CPA)

これは、各名前の最初の文字を大文字にするために使用する正規表現です。これを最初に実行し、次にルールに従ってルーチン形式に従います (Coldfusion 形式ですが、おわかりいただけると思います)。

<cfset var nameString = REReplace(LCase(nameString), "(^[[:alpha:]]|[[:blank:]][[:alpha:]])", "\U\1\E", "ALL")>

JavaScript と CSS を使用してクライアント側でこれを行うこともできますが、もっと簡単かもしれませんが、ページがクライアント側で読み込まれる前に変数を設定する必要があるため、サーバー側で行うことを好みます。

于 2011-11-16T07:11:48.430 に答える
0

私は似たようなことをしました。私が抱えていた主な問題は、人々が「リチャードR.スミスジュニア」のようなものに入ったときでした。コードをhttp://www.blackbeltcoder.com/Articles/strings/splitting-a-name-into-first-and-last-namesに投稿しました。C#ですが、VBに簡単に変換できます。

于 2011-01-28T22:21:13.510 に答える
0

確かに、簡単な解決策があります。文字列をスペースで分割し、トークンの数を数えます。2つある場合は、それらをFIRSTおよびLAST名と解釈し、3つある場合は、FIRST、MIDDLE、およびLASTと解釈します。

問題は、単純な解決策が100%正しい解決策ではないことです。誰かが常により多くのトークンを含む名前を入力したり、タイトルやスペースを含む名前を含めることができます(これは可能ですか?)。ほとんどの場合、ほとんどの名前で機能するソリューションを考え出しますが、絶対的なソリューションではありません。

Shadの推奨に従って、入力フィールドを分割します。

于 2008-09-19T16:33:00.333 に答える
0

1つの文化の人々に連絡するだけの場合を除いて、これは行いたくありません。

例えば:

グイドヴァンロッサムの姓はヴァンロッサムです。

宮崎駿の名は駿。

あなたができる最も成功することは、一般的な称号と敬礼を取り除き、いくつかのヒューリスティックを試すことです。

それでも、最も簡単な解決策は、フルネームを保存するか、名前と家族の名前を別々に尋ねることです。

于 2008-09-19T16:35:28.160 に答える
0

リストから敬礼を取り除き、スペースで分割し、list.first()を名、list.last()を名として配置し、残りをスペースで結合してミドルネームにします。そして、上記のすべてがあなたの結果を表示し、ユーザーがそれらを変更できるようにします!

于 2008-09-19T16:31:59.447 に答える
0

これを行う 100% の方法はありません。

スペースを分割して名前を理解しようとすることはできますが、最終的には間違ってしまうことがあります。それで十分な場合は、分割する方法を提供するここの回答のいずれかを選択してください.

しかし、「John Wayne」がファーストネームである「John Wayne Olson」のような名前を持つ人もいれば、「Wayne」がミドルネームである「John Wayne Olson」のような名前を持つ人もいます。その名前には、それをどのように解釈するかを教えてくれるものは何もありません。

仕方ないよ。アナログの世界です。

私のルールはとてもシンプルです。

最後の部分を取る --> 苗字
複数の部分が残っている場合は、最後の部分を取る --> ミドルネーム
残っているもの --> 名

ただし、これが 100% 正確であると仮定しないでください。また、他のハードコードされたソリューションもそうではありません。ユーザーがこれを自分で編集できるようにする必要があります。

于 2008-12-26T22:34:17.913 に答える
0

私は同意します、これには簡単な解決策はありません。しかし、VB 5.0 に関する Microsoft KB の記事で、ここで説明されている多くの議論の実際の実装であるひどいアプローチを見つけました: http://support.microsoft.com/kb/168799

このようなものはピンチで使用できます。

于 2008-12-02T20:39:14.513 に答える
0

これは愚かな用事です。これを決定論的に行うには、例外が多すぎます。さらなるレビューのためにリストを前処理するためにこれを行っている場合、少ないほど確実に多いと主張します.

  1. 敬称、タイトル、世代の接尾辞 (大きな正規表現、またはいくつかの小さな正規表現) を取り除きます。
  2. 名前が 1 つだけの場合は、'last' です。
  3. 2 つの名前だけがそれらを最初に分割する場合、最後に。
  4. 3 つのトークンと中間が最初の場合、それらを最初、中間、最後に分割します
  5. 残りを手で並べます。

処理が分割されたものを再結合する必要があるため、さらに処理を行うと、より多くの作業が作成されることがほぼ保証されます。

于 2008-09-19T16:53:38.553 に答える
-2

私はこれをしないことに同意します。Rick Van DenBoerという名前は、最終的にVanのミドルネームになりますが、これは最後の名前の一部です。

于 2008-09-19T16:32:49.990 に答える