PHPで序数接尾辞付きの数値を表示する


148

次のように数字を表示したい

  • 1を1として、
  • 2は2番目、
  • ...、
  • 150として150。

コード内の数値ごとに正しい序数接尾辞(st、nd、rd、th)を見つけるにはどうすればよいですか?


2
ここで私の答えを参照してください。stackoverflow.com/questions/69262/…その質問は.NETに対するものでしたが、私はPHPソリューションで答えたので、それが役立つはずです。
nickf

私がこれを行うと考えることができる唯一の方法は、可能性のあるすべての数、IE、if(1)、「st」、elseif(2)、「nd」などのifステートメントがif(23000)、「 nd」。大きな数字がある場合は問題ですが、コードを作成するプログラムを作成すると、ifsを出力してすべての数字をループし、コードにコピーして貼り付けることができます。
トム・グレン

2
@Tom、ルックアップテーブルの方が良いかもしれません。23000の値で初期化し、インデックスnの値を取得するだけです。nは序数にしたい数値です。
John Boker、2010年

2
爆弾大佐。あなたは素晴らしいかもしれませんが、すべてではありません。私の質問に興味を示してくれてありがとう
ArK

@John、非常に賢いアイデアです。各インデックスが検索している番号を表すだけでなく、アクセスも非常に迅速です。
トム・グレン

回答:


282

ウィキペディアから

$ends = array('th','st','nd','rd','th','th','th','th','th','th');
if (($number %100) >= 11 && ($number%100) <= 13)
   $abbreviation = $number. 'th';
else
   $abbreviation = $number. $ends[$number % 10];

$number書きたい数字はどこですか。任意の自然数で機能します。

関数として:

function ordinal($number) {
    $ends = array('th','st','nd','rd','th','th','th','th','th','th');
    if ((($number % 100) >= 11) && (($number%100) <= 13))
        return $number. 'th';
    else
        return $number. $ends[$number % 10];
}
//Example Usage
echo ordinal(100);

最初は少しわかりづらいですが、今では通常の接尾辞システムが英語でどのように機能するかを最もよく表していると思います。
erisco

5
私はあなたの解決策が好きです。さらに、0番目を生成したくない場合は、最終行を次のように変更します$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
Gavin Jackson

1
@GavinJacksonこの優れたソリューションへのあなたの追加は本当に私を助けました(+1)。計算で何が起こっているのか説明してください。理解したい。乾杯!EDIT:答えが見つかりました:条件演算子
アンドリュー・フォックス

申し訳ありませんが、111票を112票に破る必要がありました:Dデモアプリと一緒にDelphiで機能させました:pastebin.com/wvmz1CHY
Jerry Dodge

1
@HafezDivandari-よろしいですか?7.1.19でテストされ、正常に動作するようです
Iacopo

141

PHPには、この機能が組み込まれています。国際化にも対応しています!

$locale = 'en_US';
$nf = new NumberFormatter($locale, NumberFormatter::ORDINAL);
echo $nf->format($number);

この機能はPHP 5.3.0以降でのみ使用できることに注意してください。


15
なお、これも必要とPECLのインターナショナルは> = 1.0.0
rymo

4
序数を単語形式で取得できるかどうか知っていますか?つまり、第1、第2、第3などではなく、第1、第2、第3など...
its_me

@jeremy NumberFormatterを使用しようとすると、常に次のエラーがスローされますNumberFomatter file not found。これをどのように回避しましたか?
jhnferraris 14

1
@Jhnあなたは拡張機能をインストールする必要がありますapt-get install php5-intl
Aley

@Aleyなるほど。Yiiには、現在使用している組み込みのフォーマッターがあります。heh
jhnferraris

20

これは、PHPの組み込みの日付/時刻関数の同様の機能を利用して、1行で実行できます。何卒よろしくお願いいたします。

解決:

function ordinalSuffix( $n )
{
  return date('S',mktime(1,1,1,1,( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
}

詳細な説明:

組み込みdate()関数には、n日目の計算を処理するための接尾辞ロジックがあります。接尾辞はS、フォーマット文字列で指定された場合に返されます。

date( 'S' , ? );

以来date()、タイムスタンプを(のため必要と?上記)、私たちは私たちの整数を渡します$nようdayにパラメータmktime()の値をダミーと使用の1ためのhourminutesecond、とmonth

date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) );

これは実際には、月の日(つまり$n > 31)の範囲外の値で正常に失敗しますが$n、29 に上限を設定する簡単なインラインロジックを追加できます。

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) ));

唯一の正の値2017年5月)これは失敗しますが$n == 0、その特別な場合に10を追加することで簡単に修正できます。

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));

更新、2017年5月

@donatJによって観察されるように、>=20チェックは常にtrueを返すため、上記は100を超えると失敗します(「111st」など)。これらを世紀ごとにリセットするには、比較にフィルターを追加します。

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n%100>=20)+($n==0))*10 + $n%10) ));

便利なように関数にラップするだけで、すぐに使えます!


14

ここにワンライナーがあります:

$a = <yournumber>;
echo $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);

おそらく最短のソリューションです。もちろん関数でラップすることができます:

function ordinal($a) {
  // return English ordinal number
  return $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);
}

よろしく、ポール

EDIT1:11から13のコードの修正。

EDIT2:111、211、...のコードの修正

EDIT3:10の倍数でも正しく動作するようになりました。


Iこのアプローチのように、悲しいかな、それは動作しません:-( 30日は30stとして出てくる第40回は、40STとして出てくるなど。。
Flukey

1
ええ、ごめんなさい。私が思った質問を読んだとき、ちょっとこれは1行のコードで可能になるはずです。そして、私はそれをタイプしただけです。私の編集からわかるように、私は改善しています。3回目の編集が終わった後、私はそれがかなり終わったと思います。少なくとも1から150までのすべての数値が画面にうまく表示されます。
Paul

500までよさそうだ!(それ以上テストしていません)。よくできました!:-)
Flukey 2010年

13

http://www.phpro.org/examples/Ordinal-Suffix.htmlから

<?php

/**
 *
 * @return number with ordinal suffix
 *
 * @param int $number
 *
 * @param int $ss Turn super script on/off
 *
 * @return string
 *
 */
function ordinalSuffix($number, $ss=0)
{

    /*** check for 11, 12, 13 ***/
    if ($number % 100 > 10 && $number %100 < 14)
    {
        $os = 'th';
    }
    /*** check if number is zero ***/
    elseif($number == 0)
    {
        $os = '';
    }
    else
    {
        /*** get the last digit ***/
        $last = substr($number, -1, 1);

        switch($last)
        {
            case "1":
            $os = 'st';
            break;

            case "2":
            $os = 'nd';
            break;

            case "3":
            $os = 'rd';
            break;

            default:
            $os = 'th';
        }
    }

    /*** add super script ***/
    $os = $ss==0 ? $os : '<sup>'.$os.'</sup>';

    /*** return ***/
    return $number.$os;
}
?> 

9

シンプルで簡単な答えは次のとおりです。

$Day = 3; 
echo date("S", mktime(0, 0, 0, 0, $Day, 0));

//OUTPUT - rd

質問の日付で日付については何も言わない。私はとにかく賛成しました-数の範囲が32未満になることがわかっている場合、これは迅速で簡単な解決策です
cronoklee

8

これはPHP4用に作成しました。問題なく動作しており、かなり経済的です。

function getOrdinalSuffix($number) {
    $number = abs($number) % 100;
    $lastChar = substr($number, -1, 1);
    switch ($lastChar) {
        case '1' : return ($number == '11') ? 'th' : 'st';
        case '2' : return ($number == '12') ? 'th' : 'nd';
        case '3' : return ($number == '13') ? 'th' : 'rd'; 
    }
    return 'th';  
}

Vishal Kumarさん、もう少し詳しく説明してください。Tks!
イレトラ2017

4

与えられた関数を適用するだけです。

function addOrdinalNumberSuffix($num) {
  if (!in_array(($num % 100),array(11,12,13))){
    switch ($num % 10) {
      // Handle 1st, 2nd, 3rd
      case 1:  return $num.'st';
      case 2:  return $num.'nd';
      case 3:  return $num.'rd';
    }
  }
  return $num.'th';
}

3

一般的には、それを使用してecho get_placing_string(100);を呼び出すことができます

<?php
function get_placing_string($placing){
    $i=intval($placing%10);
    $place=substr($placing,-2); //For 11,12,13 places

    if($i==1 && $place!='11'){
        return $placing.'st';
    }
    else if($i==2 && $place!='12'){
        return $placing.'nd';
    }

    else if($i==3 && $place!='13'){
        return $placing.'rd';
    }
    return $placing.'th';
}
?>

2

PHPのdate();機能に依存しない機能を必要とせず、現在可能な限りコンパクトで短い機能を作りました。

コード:(合計121バイト)

function ordinal($i) { // PHP 5.2 and later
  return($i.(($j=abs($i)%100)>10&&$j<14?'th':(($j%=10)>0&&$j<4?['st', 'nd', 'rd'][$j-1]:'th')));
}

以下のよりコンパクトなコード。

次のように機能します

printf("The %s hour.\n",    ordinal(0));   // The 0th hour.
printf("The %s ossicle.\n", ordinal(1));   // The 1st ossicle.
printf("The %s cat.\n",     ordinal(12));  // The 12th cat.
printf("The %s item.\n",    ordinal(-23)); // The -23rd item.

この機能について知っておくべきこと

  • 正の整数と同じように負の整数を扱い、符号を保持します。
  • 予想どおり、-13の数値に対して11、12、13、811、812、813などを返します。
  • これは、小数をチェックしませんが、(使用場所でそれらを残してfloor($i)round($i)またはceil($i)確定申告書の冒頭で)。
  • 追加することもできます format_number($i)最後のreturnステートメントの先頭にして、コンマ区切りの整数を取得ます(数千、数百万などを表示している場合)。
  • $i入力せずに序数のサフィックスのみを返す場合は、returnステートメントの先頭からを削除するだけで済みます。

この関数は、2006年11月にリリースされたPHP 5.2以降、純粋に短い配列構文のために機能します。これより前のバージョンをお持ちの場合は、10年近く経っているのでアップグレードしてください。失敗した場合は、インライン['st', 'nd', 'rd']を一時変数に置き換えてくださいarray('st', 'nd', 'rd');

同じ関数(入力を返さない)ですが、理解を深めるための短い関数の分解図:

function ordinal($i) {
  $j = abs($i); // make negatives into positives
  $j = $j%100; // modulo 100; deal only with ones and tens; 0 through 99

  if($j>10 && $j<14) // if $j is over 10, but below 14 (so we deal with 11 to 13)
    return('th'); // always return 'th' for 11th, 13th, 62912th, etc.

  $j = $j%10; // modulo 10; deal only with ones; 0 through 9

  if($j==1) // 1st, 21st, 31st, 971st
    return('st');

  if($j==2) // 2nd, 22nd, 32nd, 582nd
    return('nd'); // 

  if($j==3) // 3rd, 23rd, 33rd, 253rd
    return('rd');

  return('th'); // everything else will suffixed with 'th' including 0th
}

コードの更新

これは、全体が14バイト短い修正バージョンです(合計107バイト)。

function ordinal($i) {
  return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');
}

または、できるだけ短い場合は25バイト短くなります(合計96バイト)。

function o($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}

この最後の関数では、単に呼び出すだけで、o(121);リストした他の関数とまったく同じように動作します。

コードの更新#2

ベンと私は協力して38バイト削減しました(合計83バイト)。

function o($i){return$i.@(($j=abs($i)%100)>10&&$j<14?th:[th,st,nd,rd][$j%10]?:th);}

これより短くなることはないと思います!しかし、間違って証明されても構わない。:)

みなさんお楽しみください。


abs()モジュラスで使用する必要はありません%
99問題-構文は1つではありません

モジュロのみに依存しても、負の符号はそのまま残ります。abs();私が必要としている負の符号を取り除きます。
nxasdf

1

mktime()を使用せずに月の日付をさらに短くしたバージョン(最大31)で、pecl intlを必要としません。

function ordinal($n) {
    return (new DateTime('Jan '.$n))->format('jS');
}

または手続き的に:

echo date_format(date_create('Jan '.$n), 'jS');

私が選んだデフォルトの月(1月)には31日があるため、これはもちろん機能します。

興味深いことに、2月(または31日なしの別の月)で試してみると、終了前に再起動します。

...clip...
31st
1st
2nd
3rd

tループの日付指定子を使用して、今月の日まで数えることができます:月の日数。


1
function ordinal($number){

    $last=substr($number,-1);
    if( $last>3 || $last==0 || ( $number >= 11 && $number <= 19 ) ){
      $ext='th';
    }else if( $last==3 ){
      $ext='rd';
    }else if( $last==2 ){
      $ext='nd';
    }else{
      $ext='st';
    }
    return $number.$ext;
  }

0

PHP.netで答えを見つけた

<?php
function ordinal($num)
{
    // Special case "teenth"
    if ( ($num / 10) % 10 != 1 )
    {
        // Handle 1st, 2nd, 3rd
        switch( $num % 10 )
        {
            case 1: return $num . 'st';
            case 2: return $num . 'nd';
            case 3: return $num . 'rd';  
        }
    }
    // Everything else is "nth"
    return $num . 'th';
}
?>

0

次に、日付関数を使用した別の非常に短いバージョンを示します。これは、任意の数で機能し(月の日付による制約はありません)、* 11番目* 12番目* 13番目は* 1番目* 2番目* 3番目の形式に従っていないことを考慮に入れます。

function getOrdinal($n)
{
    return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
}

-1

私はこの小さなスニペットが好きです

<?php

  function addOrdinalNumberSuffix($num) {
    if (!in_array(($num % 100),array(11,12,13))){
      switch ($num % 10) {
        // Handle 1st, 2nd, 3rd
        case 1:  return $num.'st';
        case 2:  return $num.'nd';
        case 3:  return $num.'rd';
      }
    }
    return $num.'th';
  }

?>

ここに


1
ChintanThummarの回答に加えて、この回答が何を提供しているかはよくわかりません。まあ、それは彼があなたのソースでコードを書いたのでなければ、ChintanThummarが著作権侵害をしたことを示唆しています...
Andreas Rejbrand
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.