Skip to content

Instantly share code, notes, and snippets.

@marcojetson
Created July 5, 2016 15:57
Show Gist options
  • Save marcojetson/01fd378d0e2baad5a8ed4ce13ed32180 to your computer and use it in GitHub Desktop.
Save marcojetson/01fd378d0e2baad5a8ed4ce13ed32180 to your computer and use it in GitHub Desktop.
Extract and reduce measurement units from strings
<?php
require __DIR__ . '/strtounits.php';
assert(strtometers('25000.23 meters') === 25000.23);
assert(strtometers('3km, 25.5 meters') === 3025.5);
<?php
/**
* @param string $str
* @return array
*/
function strtounits($str)
{
$locale = localeconv();
$units = [
'k' => 'k',
'km' => 'k',
'kms' => 'k',
'kilometer' => 'k',
'kilometers' => 'k',
'm' => 'm',
'ms' => 'm',
'meter' => 'm',
'meters' => 'm',
'c' => 'c',
'cm' => 'c',
'cms' => 'c',
'centimeter' => 'c',
'centimeters' => 'c',
];
$re = '/(?P<value>\d{1,3}(?:' . (empty($locale['thousands_sep']) ? '' : '\\' . $locale['thousands_sep'] . '?') . '\d{3})*(?:\\' . $locale['decimal_point'] . '\d+)?)\s*(?P<unit>' . join ('|', array_keys($units)) . ')/';
$count = preg_match_all($re, $str, $matches);
if ($count === 0) {
return false;
}
$result = [];
for ($i = 0; $i < $count; $i++) {
$unit = $units[$matches['unit'][$i]];
$value = str_replace($locale['thousands_sep'], '', $matches['value'][$i]);
if (!isset($result[$unit])) {
$result[$unit] = 0;
}
$result[$unit] += $value;
}
return $result;
}
/**
* @param string $str
* @return float
*/
function strtounit($str, array $multipliers)
{
$units = strtounits($str);
if ($units === false) {
return false;
}
$result = 0;
foreach ($units as $unit => $value) {
if (!isset($multipliers[$unit])) {
continue;
}
$result += $value * $multipliers[$unit];
}
return $result;
}
/**
* @param string $str
* @return float
*/
function strtokilometers($str)
{
return strtounit($str, [
'k' => 1,
'm' => 0.01,
'c' => 0.00001,
]);
}
/**
* @param string $str
* @return float
*/
function strtometers($str)
{
return strtounit($str, [
'k' => 1000,
'm' => 1,
'c' => 0.01,
]);
}
/**
* @param string $str
* @return float
*/
function strtocentimeters($str)
{
return strtounit($str, [
'k' => 100000,
'm' => 100,
'c' => 1,
]);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment