#php #arrays
Вопрос:
У меня есть длинный многомерный массив с группами чисел, насчитывающими до 100 … Например:
$list = (
array('1-4','first'),
array('5-7','next'),
array('8-10','third group'),
array('11-12','another group'),
/* ... keep going up to 100 */
array('94-97','almost done'),
array('98-100','first')
);
У меня есть случайно сгенерированный номер, который нужно вычислить с помощью строки для вывода:
$num = rand(1,100);
Я хотел бы знать, как я буду получать#, связанный внутри массива. Итак, если бы я выкатил 3, я мог бы получить первый ключ массива (1-4) и иметь возможность распечатать «первый» …. или если бы я выкатил 97, я бы получил ключ от 2-го до последнего для «почти готово» (94-97). Есть ли быстрый способ сделать это?
Спасибо
Комментарии:
1. 1. Используйте цикл для повторения. 2. Используйте
explode()
для разбора строки. 3.if()
4.return
илиbreak
.
Ответ №1:
Вы могли бы сделать что-то подобное, если структура $list
гарантирована:
$randomRoll = rand(1,100);
array_walk($list, function($ar) use ($randomRoll){
$nums = explode('-', $ar[0]);
(int) $lower = $nums[0];
(int) $upper = $nums[1];
if (($randomRoll >= $lower) amp;amp; ($randomRoll <= $upper))
{
print($ar[1]);
}
});
Комментарии:
1. В этом ответе отсутствует его образовательное объяснение.
Ответ №2:
Вы можете упростить свой массив поиска до ассоциативного, так как в нем нет пробелов от 1 до 100. Другими словами, каждое случайное число попадет в одну из известных групп, определив наибольшее число, которое меньше или равно.
Не используйте никаких функциональных итераторов (например array_filter()
, или array_walk()
), потому что они будут безоговорочно повторять весь массив поиска. Вместо этого используйте foreach()
и break
как можно скорее-это наиболее эффективно.
Код: (Демо)
$list = [
4 => 'first', // 1 - 4
7 => 'next', // 5 = 7
10 => 'third group', // 8 - 10
12 => 'another group', // 11, 12
95 => 'huge chunk', // 13 - 95
97 => 'almost done', // 96, 97
100 => 'first' // 98 - 100
];
$num = rand(1, 100);
foreach ($list as $key => $group) {
// echo "$num vs $keyn";
if ($num <= $key) {
break; // don't iterate anymore after finding group
}
}
echo "Num = $num, Group = $group";
Комментарии:
1. Предложенный ассоциативный массив в основном предотвращает возникновение перекрытий или пробелов. Голос за это. Учитывая небольшое количество записей, для меня аргумент эффективности относится к области микрооптимизации.
2. Это самый простой, самый лаконичный, точный и ресурсосберегающий метод, который я могу придумать. Это то, что я бы использовал профессионально.
Ответ №3:
Я сделал следующее… и, похоже, это работает. Если у кого-нибудь есть советы по очистке кода, дайте мне знать… Спасибо…
$dieroll = rand(1,100); // Final Roll
$numarr = array(); $j=0;
foreach ($list as $k => $v) {
$strTr = $v[0];
$nums2arr = explode("-", $strTr);
for($i=$nums2arr[0]; $i<=$nums2arr[1]; $i ) {
$numarr[] = $j;
}
$j ;
}
$roll = $list[$numarr[$dieroll-1]][1];
Комментарии:
1. В этом ответе отсутствует его образовательное объяснение.
Ответ №4:
Это решение использует array_filter. В результате снова получается 2-мерный массив с элементами, которые удовлетворяют условию функции фильтра.
$filter = function($a) use($find){
list($low,$up) = explode('-',$a[0]);
return $find >= $low AND $find <= $up;
};
$arr = array_filter($list, $filter);
полный пример:
$list = [
['1-4','first'],
['5-7','next'],
['8-10','third group'],
['11-12','another group'],
/* ... keep going up to 100 */
['94-97','almost done'],
['98-100','first']
];
//for a test is better to use a fix number
$find = 9;
$filter = function($a) use($find){
list($low,$up) = explode('-',$a[0]);
return $find >= $low AND $find <= $up;
};
$arr = array_filter($list, $filter);
echo 'Label: '.reset($arr)[1]."<br>n";
echo 'Area: '.reset($arr)[0]."<br>n";
echo 'Array-Key: '.key($arr)."<br>n";
Выход:
Label: third group
Area: 8-10
Array-Key: 2
Начиная с PHP 8.0, для этого также возможны решения с соответствием:
$num = rand(1, 100);
$group = match(true) {
$num <= 4 => 'first',
$num <= 7 => 'next',
$num <= 10 => 'third group',
$num <= 12 => 'another group',
$num <= 95 => 'huge chunk',
$num <= 97 => 'amost done',
$num <= 100 => 'first',
};
echo "Num = $num, Group = $group";