PHP'de sıra son eki olan sayıları görüntüleme


155

Numaraları aşağıdaki gibi görüntülemek istiyorum

  • 1'inci,
  • 2, 2,
  • ...,
  • 150, 150.

Kodumdaki her numara için doğru sıra son ekini (st, nd, rd veya th) nasıl bulmalıyım?


2
Cevabımı burada görün. stackoverflow.com/questions/69262/… Bu soru .NET içindi, ancak bir PHP çözümü ile cevap verdim, bu yüzden size yardımcı olmalı.
nickf

Bunu yapmayı düşünebilmemin tek yolu, sahip olabileceğiniz her sayı için bir if ifadesine sahip olmaktır, IE, if (1) sonra "st" elseif (2) sonra "nd" vb. İf (23000) then " nd ". Büyük sayılarınız varsa bu bir sorundur, ancak kodu sizin için yazmak için bir program yazabilirseniz, kodunuza kopyalayıp yapıştırmanız için if'leri yazdıran tüm numaraları döngüye alabilir.
Tom Gullen

2
@Tom, bir arama tablosu daha iyi olabilir, sadece 23000 değerleriyle başlatın ve n dizinindeki değeri alın, burada n, sıralı olmasını istediğiniz sayıdır.
John Boker

2
Albay Şarapnel. Harika olabilirsin ama hepsi değil.
Sorumla

@John, çok çok akıllıca bir fikir, her bir indeks aradığınız sayıyı temsil ettiği gibi, erişim çok hızlı olacaktır.
Tom Gullen

Yanıtlar:


290

wikipedia'dan :

$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];

$numberYazmak istediğin numara nerede . Herhangi bir doğal sayı ile çalışır.

İşlev olarak:

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

İlk başta anlaşılması biraz zor olsa da, şimdi sıralı sonek sisteminin İngilizce için nasıl çalıştığını en iyi temsil ettiğini düşünüyorum.
erisco

6
Çözümünüzü beğendim. Buna ek olarak, 0'ıncı satırı oluşturmamayı tercih ediyorsanız , son satırı şu şekilde değiştirin$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
Gavin Jackson

1
@GavinJackson, bu mükemmel çözüme eklemeniz bana gerçekten yardımcı oldu (+1). Hesaplamada neler olduğunu bana açıklar mısınız? Anlamak istiyorum. Şerefe! DÜZENLEME: Bir cevap bulundu: koşullu operatör
Andrew Fox

Üzgünüm, 111 oyu 112'ye kırmak zorunda kaldı: D Delphi'de bir demo uygulamasıyla birlikte bir işlev yaptı: pastebin.com/wvmz1CHY
Jerry Dodge

1
@HafezDivandari - emin misin? 7.1.19 ile test edildi ve iyi çalışıyor gibi görünüyor
Iacopo

149

PHP, bunun için yerleşik işlevselliğe sahiptir . Uluslararasılaşmayı bile idare ediyor!

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

Bu işlevselliğin yalnızca PHP 5.3.0 ve sonrasında kullanılabildiğini unutmayın.


15
Bunun ayrıca PECL intl> = 1.0.0
rymo

4
Sıra numarasını kelime biçiminde almanın mümkün olup olmadığını biliyor musunuz? yani 1., 2., 3. yerine birinci, ikinci, üçüncü, vb ...
its_me

@jeremy NumberFormatter'ı kullanmaya çalıştığımda, her zaman bir hata atıyor NumberFomatter file not found. Bu konuda nasıl çalıştınız?
jhnferraris

1
@Jhn uzantıyı yüklemelisinizapt-get install php5-intl
Aley,

@Aley anlıyorum. Yii'de şu anda kullandığımız yerleşik bir formatlayıcı var. heh
jhnferraris

21

Bu, PHP'nin yerleşik tarih / saat işlevlerindeki benzer işlevlerden yararlanılarak tek bir satırda gerçekleştirilebilir. Alçakgönüllülükle sunuyorum:

Çözüm:

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

Detaylı açıklama:

Yerleşik date()fonksiyonu inci günlük-of-the-aylık hesaplamaları işlemek için sonek mantığı vardır. Sonek, Sbiçim dizesinde verildiğinde döndürülür :

date( 'S' , ? );

Yana date()bir zaman damgası (için gerektirir ?yukarıda), bizim tamsayı geçmek olacak $nşekilde dayparametre mktime()değerleri kukla ve kullanım 1için hour, minute, second, ve month:

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

Bu aslında ayın bir günü için aralık dışı değerlerde zarif bir şekilde başarısız olur (yani $n > 31), ancak $n29'da sınırlamak için bazı basit satır içi mantık ekleyebiliriz :

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

Tek pozitif değer( Mayıs 2017 ) bu başarısız olur $n == 0, ancak bu özel durumda 10 ekleyerek kolayca düzeltilebilir:

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

Güncelleme, Mayıs 2017

@DonatJ tarafından gözlemlendiği gibi, >=20kontroller her zaman doğruya döndüğünden, yukarıdaki 100'ün üzerinde başarısız olur (ör. "111.") . Bunları her yüzyılda sıfırlamak için, karşılaştırmaya bir filtre ekliyoruz:

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

Kolaylık sağlamak için onu bir fonksiyona sarın ve başlayın!


14

İşte tek satırlık:

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

Muhtemelen en kısa çözüm. Elbette bir işlevle sarılabilir:

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

Saygılarımızla, Paul

DÜZENLEME1: 11'den 13'e kadar kodun düzeltilmesi.

EDIT2: 111, 211, ... için kod düzeltmesi

DÜZENLEME3: Artık 10'un katları için de doğru çalışıyor.


Bu yaklaşımı beğendim ama ne yazık ki işe yaramıyor :-( 30. 30. 30. 40. 40. 40. vb.
Flukey

1
Evet üzgünüm. Düşündüğüm soruyu okuduğumda, bu tek bir kod satırı ile mümkün olmalı. Ve sadece yazdım. Düzenlemelerimden de gördüğünüz gibi gelişiyorum. Üçüncü düzenlemeden sonra şimdi oldukça bittiğini düşünüyorum. En azından 1'den 150'ye kadar tüm sayılar ekranımda güzelce yazdırılıyor.
Paul

500'e kadar iyi görünüyor! (bundan daha fazlasını test etmedim). İyi iş! :-)
Flukey

13

dan 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

Basit ve Kolay Cevap:

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

//OUTPUT - rd

Tho sorusunda tarihler hakkında hiçbir şey söylemiyor. Yine de oy verdim - sayı aralığının <32 olacağını bildiğinizde bu hızlı ve basit bir çözüm
cronoklee

8

Bunu PHP4 için yazdım. İyi çalışıyor ve oldukça ekonomik.

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, bunu biraz daha genişletebilir / açıklayabilir misiniz? Tks!
iletras

4

sadece verilen işlevi uygulamanız gerekir.

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

Genel olarak, bunu kullanabilir ve 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

date();Gerekli olmadığı için PHP'nin işlevine güvenmeyen , aynı zamanda onu şu anda mümkün olduğunu düşündüğüm kadar kompakt ve kısa yapan bir işlev yaptım.

Kod : (toplam 121 bayt)

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

Aşağıda daha kompakt kod.

Aşağıdaki gibi çalışır :

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.

Bu işlev hakkında bilinmesi gerekenler :

  • Pozitif tamsayılarla aynı olan negatif tamsayılarla ilgilenir ve işareti korur.
  • Beklendiği gibi on sayılar için 11., 12., 13., 811., 812., 813. Vb. Döndürür .
  • Bu ondalık basamakları kontrol etmez, ancak (kullanım yerde bırakacak floor($i), round($i)ya da ceil($i)son iade ifade başında).
  • format_number($i)Virgülle ayrılmış bir tam sayı elde etmek için son dönüş ifadesinin başına da ekleyebilirsiniz (binleri, milyonları vb. Görüntülüyorsanız).
  • $iYalnızca sıra soneki girdiğiniz şey olmadan döndürmek istiyorsanız, return ifadesinin başından kaldırabilirsiniz .

Bu işlev, yalnızca kısa dizi sözdizimi nedeniyle Kasım 2006'da yayınlanan PHP 5.2'den başlayarak çalışır. Bundan önce bir sürümünüz varsa, lütfen güncellemeyi neredeyse on yıl geçirdiğiniz için yükseltin! Başarısız olursa, satır içi ['st', 'nd', 'rd']olanı içeren geçici bir değişkenle değiştirin array('st', 'nd', 'rd');.

Aynı işlev (girdiyi döndürmeden), ancak daha iyi anlamak için kısa işlevimin parçalara ayrılmış bir görünümü:

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
}

Kod Güncellemesi :

İşte 14 tam bayt daha kısa (toplam 107 bayt) değiştirilmiş bir sürüm:

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

Veya 25 bayt daha kısa (toplam 96 bayt) olabildiğince kısa:

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

Bu son işlevle, basitçe arayın o(121);ve listelediğim diğer işlevlerle tam olarak aynı şeyi yapacaktır.

Kod Güncellemesi # 2 :

Ben ve ben birlikte çalıştık ve 38 bayt (toplam 83 bayt) azalttık:

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

Bundan daha kısalabileceğini düşünmüyoruz! Ancak yanlış olduğu kanıtlanmaya istekli. :)

Umarım hepiniz eğlenirsiniz.


abs()modül ile kullanmanıza gerek yok%
99 Problemler - Sözdizimi bir değil

Yalnızca modulo'ya güvenmek, negatif işaretini yerinde bırakmaya devam edecektir. abs();ihtiyacım olan negatif işareti kaldırır.
nxasdf

1

Mktime () kullanmak yerine ve pecl intl gerektirmeyen ay içindeki tarihler için (31'e kadar) daha da kısa bir versiyon:

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

veya prosedürel olarak:

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

Elbette bu işe yarıyor çünkü seçtiğim varsayılan ayın (Ocak) 31 günü var.

İlginçtir ki, Şubat ayında (veya 31 gün olmadan başka bir ay) denerseniz, sonundan önce yeniden başlar:

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

Böylece, döngünüzdeki tarih belirleyicisiyle bu ayın günlerini sayabilirsiniz t: aydaki gün sayısı.


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'te bir cevap bulundu

<?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

İşte tarih işlevlerini kullanan çok kısa bir versiyon. Herhangi bir sayı için çalışır (ayın günleri ile sınırlandırılmamıştır) ve * 11. * 12. * 13. * 1. * 2. * 3. formatı takip etmediğini dikkate alır.

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

-1

Bu küçük parçacığı seviyorum

<?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';
  }

?>

BURAYA


1
Bu cevabın ChintanThummar'ın cevabına ek olarak ne sunduğundan tam olarak emin değilim. Bu, ChintanThummar'ın, kodu kaynağınıza yazmadığı sürece bir telif hakkı ihlali yaptığına işaret ediyor ...
Andreas Rejbrand
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.