Как преобразовать "1d2h3m" в массив ( "день" => 1, "час" => 2, "минуты" => 3)?
Есть $time = "1d2h3m";
, поэтому я хочу, чтобы это было в массиве вроде array("day" => 1, "hour" => 2,"minutes"=>3)
, поэтому я попытался с помощью explode()
<?php
$time = "1d2h3m";
$day = explode("d", $time);
var_dump($day); // 0 => string '1' (length=1)
// 1 => string '2h3m' (length=4)
?>
Здесь я понятия не имею, как сделать массив вроде array("day" => 1, "hour" => 2,"minutes"=>3)
Ответы
Ответ 1
Простой sscanf
проанализирует это в массиве. Затем вы array_combine
со списком нужных вам ключей.
Пример:
$time = "1d2h3m";
$result = array_combine(
['day', 'hour', 'minutes'],
sscanf($time, '%dd%dh%dm')
);
print_r($result);
Вывод:
Array
(
[day] => 1
[hour] => 2
[minutes] => 3
)
Чтобы разбить используемый формат sscanf
:
-
%d
- считывает (подписанное) десятичное число, выводит целое число
-
d
- соответствует буквенному символу "d"
-
%d
- (как первый)
-
h
- соответствует буквенному символу "h"
-
%d
- (как первый)
-
m
- соответствует буквенному символу "m" (необязательно, поскольку он приходит после всего, что вы хотите захватить)
Он также отлично работает с несколькими цифрами и отрицательными значениями:
$time = "42d-5h3m";
Array
(
[day] => 42
[hour] => -5
[minutes] => 3
)
Ответ 2
Вы должны пойти с регулярным выражением для этого случая
<?php
$time = "1d2h3m";
if(preg_match("/([0-9]+)d([0-9]+)h([0-9]+)m/i",$time,$regx_time)){
$day = (int) $regx_time[1];
$hour = (int) $regx_time[2];
$minute = (int) $regx_time[3];
var_dump($day);
}
?>
Объяснение:
[0-9]: сопоставьте любые цифры от 0 до 9
[0-9] +: означает, что цифры соответствуют хотя бы одному символу
([0-9] +): означает, чтобы цифры соответствовали хотя бы одному символу и фиксировали результаты
/........../i: установите регистр insenstive для шаблона регулярного выражения, которое вы установили
Regex - это лучший способ лексики и синтаксического анализа. И хорошо изучить регулярное выражение. Почти все языки программирования используют regex
Ответ 3
Настраиваемая функция и самое главное, что вы можете поймать исключение, если вход не сформирован правильно
/**
* @param $inputs string : date time on this format 1d2h3m
* @return array on this format "day" => 1,
* "hour" => 2,
* "minutes" => 3
* @throws Exception
*
*/
function dateTimeConverter($inputs) {
// here you can customize how the function interprets input data and how it should return the result
// example : you can add "y" => "year"
// "s" => "seconds"
// "u" => "microsecond"
// key, can be also a string
// example "us" => "microsecond"
$dateTimeIndex = array("d" => "day",
"h" => "hour",
"m" => "minutes");
$pattern = "#(([0-9]+)([a-z]+))#";
$r = preg_match_all($pattern, $inputs, $matches);
if ($r === FALSE) {
throw new Exception("can not parse input data");
}
if (count($matches) != 4) {
throw new Exception("something wrong with input data");
}
$datei = $matches[2]; // contains number
$dates = $matches[3]; // contains char or string
$result = array();
for ($i=0 ; $i<count ($dates) ; $i++) {
if(!array_key_exists($dates[$i], $dateTimeIndex)) {
throw new Exception ("dateTimeIndex is not configured properly, please add this index : [" . $dates[$i] . "]");
}
$result[$dateTimeIndex[$dates[$i]]] = (int)$datei[$i];
}
return $result;
}
Ответ 4
Другое решение для регулярных выражений
$subject = '1d2h3m';
if(preg_match('/(?P<day>\d+)d(?P<hour>\d+)h(?P<minute>\d+)m/',$subject,$matches))
{
$result = array_map('intval',array_intersect_key($matches,array_flip(array_filter(array_keys($matches),'is_string'))));
var_dump($result);
}
Возвращает
array (size=3)
'day' => int 1
'hour' => int 2
'minute' => int 3
Ответ 5
Используйте эту простую реализацию с заменой строки и массивом.
<?php
$time = "1d2h3m";
$time=str_replace(array("d","h","m")," " ,$time);
$time=array_combine(array("day","hour","minute"),explode(" ",$time,3));
print_r($time);
?>
Ответ 6
Я думаю, что для такой маленькой строки, и если формат всегда будет одним и тем же, вы можете использовать array_push
и substr
, чтобы извлечь из строки цифры и поместить их в массив.
<?php
$time = "1d2h3m";
$array = array();
array_push($array, (int) substr($time, 0, 1));
array_push($array, (int) substr($time, 2, 1));
array_push($array, (int) substr($time, 4, 1));
var_dump($array);
?>
Ответ 7
В этом подходе используется регулярное выражение для извлечения значений и массива для сопоставления букв со словами.
<?php
// Initialize target array as empty
$values = [];
// Use $units to map the letters to the words
$units = ['d'=>'days','h'=>'hours','m'=>'minutes'];
// Test value
$time = '1d2h3m';
// Extract out all the digits and letters
$data = preg_match_all('/(\d+)([dhm])/',$time,$matches);
// The second (index 1) array has the values (digits)
$unitValues = $matches[1];
// The third (index 2) array has the keys (letters)
$unitKeys = $matches[2];
// Loop through all the values and use the key as an index into the keys
foreach ($unitValues as $k => $v) {
$values[$units[$unitKeys[$k]]] = $v;
}
Ответ 8
$d = [];
list($d['day'],$d['hour'],$d['minutes']) = preg_split('#[dhm]#',"1d2h3m");
Ответ 9
Не можете ли вы просто взорвать его 3 раза...
// Define an array
$day = explode("d", $time);
// add it in array with key as "day" and first element as value
$hour= explode("h", <use second value from above explode>);
// add it in array with key as "hour" and first element as value
$minute= explode("m", <use second value from above explode>);
// add it in array with key as "minute" and first element as value
У меня сейчас нет рабочего примера, но я думаю, что это сработает.
Ответ 10
Мы можем также достичь этого, используя str_replace() и explode().
$time = "1d2h3m";
$time = str_replace(array("d","h","m"), "*", $time);
$exp_time = explode("*", $time);
$my_array = array( "day"=>(int)$exp_time[0],
"hour"=>(int)$exp_time[1],
"minutes"=>(int)$exp_time[2] );
var_dump($my_array);
Ответ 11
$time = "1d2h3m";
$split = preg_split("/[dhm]/",$time);
$day = array(
"day" => $split[0]
"hour" => $split[1]
"minutes" => $split[2]
);
Ответ 12
Вы можете использовать однострочное решение,
$time = "1d2h3m";
$day = array_combine(
array("day","hour","months") ,
preg_split("/[dhm]/", substr($time,0,-1) )
);
Ответ 13
Здесь есть много отличных ответов, но я хочу добавить еще один, чтобы показать более общий подход.
function parseUnits($input, $units = array('d'=>'days','h'=>'hours','m' => 'minutes')) {
$offset = 0;
$idx = 0;
$result = array();
while(preg_match('/(\d+)(\D+)/', $input,$match, PREG_OFFSET_CAPTURE, $offset)) {
$offset = $match[2][1];
//ignore spaces
$unit = trim($match[2][0]);
if (array_key_exists($unit,$units)) {
// Check if the unit was allready found
if (isset($result[$units[$unit]])) {
throw new Exception("duplicate unit $unit");
}
// Check for corect order of units
$new_idx = array_search($unit,array_keys($units));
if ($new_idx < $idx) {
throw new Exception("unit $unit out of order");
} else {
$idx = $new_idx;
}
$result[$units[trim($match[2][0])]] = $match[1][0];
} else {
throw new Exception("unknown unit $unit");
}
}
// add missing units
foreach (array_keys(array_diff_key(array_flip($units),$result)) as $key) {
$result[$key] = 0;
}
return $result;
}
print_r(parseUnits('1d3m'));
print_r(parseUnits('8h9m'));
print_r(parseUnits('2d8h'));
print_r(parseUnits("3'4\"", array("'" => 'feet', '"' => 'inches')));
print_r(parseUnits("3'", array("'" => 'feet', '"' => 'inches')));
print_r(parseUnits("3m 5 d 5h 1M 10s", array('y' => 'years',
'm' => 'months', 'd' =>'days', 'h' => 'hours',
'M' => 'minutes', "'" => 'minutes', 's' => 'seconds' )));
print_r(parseUnits("3m 5 d 5h 1' 10s", array('y' => 'years',
'm' => 'months', 'd' =>'days', 'h' => 'hours',
'M' => 'minutes', "'" => 'minutes', 's' => 'seconds' )));
Ответ 14
Вы можете использовать этот fn для получения форматированного массива, который также проверяет правильность строки:
function getFormatTm($str)
{
$tm=preg_split("/[a-zA-z]/", $str);
if(count($tm)!=4) //if not a valid string
return "not valid string<br>";
else
return array("day"=>$tm[0],"hour"=>$tm[1],"minutes"=>$tm[2]);
}
$t=getFormatTm("1d2h3m");
var_dump($t);
Ответ 15
Этот ответ не 100% относится к определенному формату входной строки из вопроса.
Но он основан на механизме синтаксического анализа PHP (это не мой собственный синтаксический анализ даты).
PHP >= 5.3.0 имеет класс DateInterval
.
Вы можете создавать объекты DateInterval из укусов в двух форматах:
$i = new DateInterval('P1DT12H'); // ISO8601 format
$i = createFromDateString('1 day + 12 hours'); // human format
Официальные документы PHP: http://php.net/manual/en/dateinterval.createfromdatestring.php
В формате ISO8601 P
означает "период". Формат поддерживает три формы периодов:
Заглавные буквы означают следующее:
- P - это обозначение продолжительности (исторически называемое "периодом" ), размещенное в начале представления продолжительности.
- Y - это обозначение года, которое следует за количеством лет.
- M - это обозначение месяца, которое следует за количеством месяцев.
- W - это указатель недели, который следует за значением числа
недель.
- D - это обозначение дня, которое следует за значением числа
дни.
- T - обозначение времени, которое предшествует компонентам времени
представление.
- H - это часовой указатель, который следует за значением числа
ч.
- M - это минутный указатель, который следует за количеством
мин.
- S - это второй указатель, который следует за количеством
секунд.
Например, " P3Y6M4DT12H30M5S" представляет собой продолжительность " три года, шесть месяцев, четыре дня, двенадцать часов, тридцать минут и пять секунд".
Подробнее см. https://en.wikipedia.org/wiki/ISO_8601#Durations.
Ответ 16
Один код строки.
$result = array_combine(array("day", "hour", "minutes"), $preg_split('/[dhm]/', "1d2h3m", -1, PREG_SPLIT_NO_EMPTY));
Ответ 17
Вы можете использовать этот код.
<?php
$str = "1d2h3m";
list($arr['day'],$arr['day'],$arr['hour'],$arr['hour'],$arr['minute'],$arr['minute']) = $str;
print_r($arr);
?>
ВЫХОД
Array (
[minute] => 3
[hour] => 2
[day] => 1
)
DEMO