1

フルネームをシングルネーム、ミディアムネーム、姓に分割するにはどうすればよいですか?

もちろん、すべての可能性をカバーすることは不可能です。ルールは 1 つだけです。単語の後に 3 文字以下の単語がある場合は、次の単語と結合する必要があります。

また、フルネームは3語以上だと思います。

どうやって始めればいいのか本当にわかりません。

例えば:

ジョン・マーティン・ジャクソン:

  • name1: ジョン
  • name2: マーティン
  • name3: ジャクソン

スティーブン・ポンセ・デ・レオン・プレスリー

  • name1: スティーブン
  • name2: ポンセ デ レオン
  • name3: プレスリー

マイケル・デ・ラ・ロサ・マーティン・ジャクソン:

  • name1: マイケル・デ・ラ・ロサ
  • name2: マーティン
  • name3: ジャクソン

:S

4

3 に答える 3

3

本当に凝った正規表現がそれを可能にします。1 つの名前に一致させるには、次を使用します。

/\S+((\s+\S{1,3})+\s+\S+)*/

次に、それらの 3 つを一致しないグループと結合しますが、それぞれが 1 つにまとめられ、空白で結合されます。

/^(\S+(?:(?:\s+\S{1,3})+\s+\S+)*)\s+(\S+(?:(?:\s+\S{1,3})+\s+\S+)*)\s+(\S+(?:(?:\s+\S{1,3})+\s+\S+)*)$/

ミドルネームのない人と一致させるには、それをオプションにします:

/^(\S+(?:(?:\s+\S{1,3})+\s+\S+)*)(?:\s+(\S+(?:(?:\s+\S{1,3})+\s+\S+)*))?\s+(\S+(?:(?:\s+\S{1,3})+\s+\S+)*)$/

更新: 1 つの正規表現で名前全体を一致させようとしないでください。グローバル フラグを指定して最初の (単純な) 正規表現を使用するだけです。

> "Steven Ponce de Leon Presley".match(/\S+((\s+\S{1,3})+\s+\S+)*/g)
["Steven", "Ponce de Leon", "Presley"]

説明:

/
 \S+      match a word
 (         followed by any number of
  (         at least one
   \s+       whitespace-separated
   \S{1,3}   up-to-three-letters word
  )+
  \s+       and a whitespace-separated
  \S+       word
 )*
/g

ただし、いくつかの文字列関数と配列関数を使用したアルゴリズムを使用すると、何が起こるかが明確になり、マッチング プロセスをよりカスタマイズできるようになると思います。

var names = input.split(/s+/);
if (names.length < 2)
    return; // special case handling for only one word
var short = 0;
for (var i=names.length-2; i>=0; i--) {
    // starting at the second-to-last, I expect names not to end with a short one
    if (names[i].length < 4) {
        short++;
    } else if (short) {
        names[i] += " "+names.splice(i+1, short+1).join(" ");
        short = 0;
    }
}
return names; // an Array with at least one name
于 2012-08-02T23:05:13.750 に答える
1

このようなものはどうですか?

function split_name(name) {
    var parts = name.split(" ");
    var num_parts = parts.length;
    var i = 0;
    var names = [];

    function in_bounds() {
        return i < num_parts;
    }
    function next_part() {
        i += 1;
        return parts[i - 1];
    }
    function part_is_short() {
        return parts[i].length < 4;
    }
    function last_part_was_short() {
        return parts[i-1].length < 4;
    }
    function next_name() {
        var name = next_part();
        if (in_bounds() && part_is_short()) {
            name += " " + next_part();
            while(in_bounds() && last_part_was_short()) {
                name += " " + next_part();
            }
        }
        return name;
    }

    while (in_bounds()) {
        names.push(next_name());
    }

    return names;
}

JSFiddle: http://jsfiddle.net/nLe7S/2/

これは、これまでで最もパフォーマンスの高いアルゴリズムではありません。正規表現の専門家は、おそらく 1 行で同じことを行うことができますが、少なくともこの方法では、人間にとって読みやすいものになります。(更新: Bergiが正規表現の第一人者であることを証明したようです。:)

それはあなたが説明したことを大まかに行いますが、ニーズに合わせて調整する必要があります。たとえば、見つかった数の「サブネーム」を含む配列を返します。したがって、ミドル ネームが見つからない場合は、長さ 2 の配列が返されます。一方、3 つ以上の名前が見つかる場合もあります。それをどう処理するかを考える必要があります。

于 2012-08-02T23:08:18.563 に答える