PHPで正規表現を読むことから始めます。例えば:
$floorarray = preg_split("/\sfloor\s/i", $floorstring)
その他の便利な関数は、、preg_grep
などpreg_match
です。
編集:より完全なソリューションを追加しました。
このソリューションは、床を説明する文字列を入力として受け取ります。次のようなさまざまな形式にすることができます。
- 102階
- 百二階
- 百二階
- 百二階
- 102階
- 102階
- 等
入力ファイルの例を見るまでは、これで十分だとあなたの投稿から推測しています。
<?php
$errorLog = 'error-log.txt'; // a file to catalog bad entries with bad floors
// These are a few example inputs
$addressArray = array('Fifty-second Floor', 'somefloor', '54th floor', '52qd floor',
'forty forty second floor', 'five nineteen hundredth floor', 'floor fifty-sixth second ninth');
foreach ($addressArray as $id => $address) {
$floor = parseFloor($id, $address);
if ( empty($floor) ) {
error_log('Entry '.$id.' is invalid: '.$address."\n", 3, $errorLog);
} else {
echo 'Entry '.$id.' is on floor '.$floor."\n";
}
}
function parseFloor($id, $address)
{
$floorString = implode(preg_split('/(^|\s)floor($|\s)/i', $address));
if ( preg_match('/(^|^\s)(\d+)(st|nd|rd|th)*($|\s$)/i', $floorString, $matchArray) ) {
// floorString contained a valid numerical floor
$floor = $matchArray[2];
} elseif ( ($floor = word2num($floorString)) != FALSE ) { // note assignment op not comparison
// floorString contained a valid english ordinal for a floor
; // No need to do anything
} else {
// floorString did not contain a properly formed floor
$floor = FALSE;
}
return $floor;
}
function word2num( $inputString )
{
$cards = array('zero',
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten',
'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty');
$cards[30] = 'thirty'; $cards[40] = 'forty'; $cards[50] = 'fifty'; $cards[60] = 'sixty';
$cards[70] = 'seventy'; $cards[80] = 'eighty'; $cards[90] = 'ninety'; $cards[100] = 'hundred';
$ords = array('zeroth',
'first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth', 'tenth',
'eleventh', 'twelfth', 'thirteenth', 'fourteenth', 'fifteenth', 'sixteenth', 'seventeenth', 'eighteenth', 'nineteenth', 'twentieth');
$ords[30] = 'thirtieth'; $ords[40] = 'fortieth'; $ords[50] = 'fiftieth'; $ords[60] = 'sixtieth';
$ords[70] = 'seventieth'; $ords[80] = 'eightieth'; $ords[90] = 'ninetieth'; $ords[100] = 'hundredth';
// break the string at any whitespace, dash, comma, or the word 'and'
$words = preg_split( '/([\s-,](?!and\s)|\sand\s)/i', $inputString );
$sum = 0;
foreach ($words as $word) {
$word = strtolower($word);
$value = array_search($word, $ords); // try the ordinal words
if (!$value) { $value = array_search($word, $cards); } // try the cardinal words
if (!$value) {
// if temp is still false, it's not a known number word, fail and exit
return FALSE;
}
if ($value == 100) { $sum *= 100; }
else { $sum += $value; }
}
return $sum;
}
?>
一般的なケースでは、単語を数字に解析するのは簡単ではありません。これについて議論している私が見つけた最高のスレッドはここにあります。数字を単語に変換するという逆問題ほど簡単ではありません。私のソリューションは、2000未満の数値に対してのみ機能し、エラーをスローするのではなく、形成が不十分な構造を自由に解釈します。また、スペルミスに対してはまったく回復力がありません。例えば:
- 40秒=82
- 519100分の1=2400
- 56秒9=67
多くの入力があり、それらのほとんどが整形式である場合、問題のエントリの短いリストを手動で修正できるため、スペルミスでエラーをスローすることはそれほど大きな問題ではありません。ただし、アプリケーションによっては、不正な入力をサイレントに受け入れることが実際の問題になる可能性があります。変換コードをより堅牢にする価値があるかどうかを判断する際に考慮すべきことです。