/** * val() should return int if var is a long-length integer name */ public function testVal_returnsInt_ifVarIsLongName() { return $this->assertEquals(Num::val('one million four hundred thirty-seven thousand five hundred twenty-two'), 1437522); }
/** * Numbers a street address accordingly * * A street address contains a numeric street address in addition to, potentially, * a numeric street name (e.g., "123 101st st"). The street name can be a number * ("101"), an ordinal (e.g., "101st"), or a cardinal (e.g., "one hundred and * first"). Ultimately, all of those should resolve to the same norm. * * For example: * * self::number("123 101 st"); // returns "123 101 st" * self::number("123 101st st"); // returns "123 101 st" * self::number("123 one hundred first st"); // returns "123 101 st" * self::number("123 one hundred and first st"); // returns "123 101 st" * * @since 0.1.0 * @param string $street the street address to number * @return string */ protected static function number($street) { // validate street if ($street === null || !is_string($street)) { throw new \InvalidArgumentException(__METHOD__ . "() expects parameter one to be a string street address"); } // break $street into words $words = explode(' ', $street); // get the numeric value of each word (or zero if the word is not a number) // for example, ["123", "one", "hundred", "and", "first", "st"] will become // [123, 1, 100, 0, 1, 0] // $numbers = array_map(function ($v) { return \Jstewmc\PhpHelpers\Num::val($v); }, $words); // if the street address has numeric words // for example, in the example above, there are three "number words" ("one", // "hundred", and "first") // $hasNumerics = count(array_diff(array_filter($numbers), $words)); if ($hasNumerics > 0) { // we're going to replace the numeric words with their value // for example, ["123", "one", "hundred", "and", "first", "st"] becomes // ["123", "101", "st"] // $newWords = array(); // loop through the words and determine exactly which words need replacing // a word needs replacing if the word's numeric value is not zero and it isn't // already a number in the address, it needs to be replaced // $numerics = array(); foreach ($words as $k => $word) { $numerics[] = $numbers[$k] !== 0 && $numbers[$k] != $word; } // loop through the words (again) $number = array(); foreach ($words as $k => $word) { // if the word is a "number word", add it to the number // otherwise, if the word is "and", the number isn't empty, and the next word // is a number word, add it to the number // finally, the word is not a number word and the number is finished // if ($numerics[$k]) { $number[] = $word; } elseif ($word === 'and' && !empty($number) && array_key_exists($k + 1, $numerics) && $numerics[$k + 1]) { $number[] = $word; } else { // if a number exists it's complete // get the number's value, append it to new words, and reset the number // if (!empty($number)) { $number = implode(' ', $number); $newWords[] = \Jstewmc\PhpHelpers\Num::val($number); $number = array(); } $newWords[] = $word; } } // glue the street address back together again $street = implode(' ', $newWords); } return $street; }