У меня есть следующие значения в массиве,
$values = array(
"1/4x1/4x1",
"1/2x1/2x1",
"3/4x3/4x1",
"1/4x1/4x2",
"1/2x1/2x2",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1");
Учитывая числа между «х», я хочу, чтобы в порядке возрастания значений, как показано ниже,
$values = array(
"1/4x1/4x1",
"1/4x1/4x2",
"1/2x1/2x1",
"1/2x1/2x2",
"3/4x3/4x1",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1");
Я новичок в PHP. Есть ли какие-то конкретные функции для этого? Если нет, пожалуйста, помогите найти способ найти решение. Благодарю.
Это немного сложно, но вы можете избежать использования eval
:
// Transpose resulting 2x2 matrix using array_map behavior of
// tacking an arbitrary number of arrays and zipping elements, when null
// giving as a callback.
$evaluated = array_map(null, ...array_map(function ($factors) {
return array_map(function ($factor) {
// Explode fraction (into array with two elements)
// and destruct it into variables.
// `@` will silent the notice if not a fraction given (array with one
// element).
@list($dividend, $divisor) = explode('/', $factor); // **
// If divisor is given then calculate a fraction.
return $divisor
? floatval($dividend) / floatval($divisor)
: floatval($dividend);
}, explode('x', $factors));
}, $values));
// Assign values array by reference as a last element.
$evaluated[] =& $values;
// Unpack all arrays (three columns of fractions and given array) and pass
// them to `array_multisort` function, that will sort in turns by each of
// the columns.
array_multisort(...$evaluated);
print_r($values);
Итак, в основном, мы отображаем каждый элемент из массива в массив вычисленных фракций, а затем транспонируем этот массив, чтобы в итоге получилось три массива, представляющих столбцы. Затем мы передаем эти три массива вместе с данным массивом в array_multisort
, это берет данный массив по ссылке и переупорядочивает его, как мы хотим.
Вот демо.
Не использовать eval()
! Это зло И вы можете легко избежать этого. Вам нужно создать метод обратного вызова для usort () который сравнивает размеры (и при необходимости преобразует дроби в числовые значения).
Я предполагаю, что у вас всегда есть 3 измерения, и они являются положительным целым числом или дробью. Я также предполагаю, что вы сортируете не по объему, а по измерению 1, измерению 2, измерению 3.
/**
* usort callback to sort dimensions
* @param {string} $a first comparable value
* @param {string} $b second comparable value
* @returns {int} 0, 1 or -1
*/
function sortByDimension($a, $b) {
$dimA = getNumericDimensions($a);
$dimB = getNumericDimensions($b);
// first dimension is the same: compare deeper
if ($dimA[0] == $dimB[0]) {
// second dimension is the same too: compare deeper
if ($dimA[1] == $dimB[1]) {
if ($dimA[2] == $dimB[2]) {
// value is the same: return 0
return 0;
}
// value A is larger: return 1, value B is larger: return -1
return ($dimA[2] > $dimB[2]) ? 1 : -1;
}
return ($dimA[1] > $dimB[1]) ? 1 : -1;
}
return ($dimA[0] > $dimB[0]) ? 1 : -1;
}
/**
* converts a string value to an array of numeric values
* @param {string} $val string of dimensions AxBxC
* @returns {array} an array with 3 dimensions and numeric values
*/
function getNumericDimensions($val) {
// split the value into the 3 dimensions
$dimensions = explode('x', $val);
// loop through the values and make them numeric
// note: the loop is per reference: we override the values!
foreach ($dimensions as &$dim) {
// check if it is a fraction
if (strpos($dim, '/') !== false) {
// split the fraction by the /
$fraction = explode('/', $dim);
// calculate a numeric value
$dim = $fraction[0] / $fraction[1];
} else {
// make it an integer
$dim = (int)$dim;
}
}
return $dimensions;
}
$values = array(
"1/4x1/4x1",
"1/2x1/2x1",
"3/4x3/4x1",
"1/4x1/4x2",
"1/2x1/2x2",
"3/4x3/4x2",
"1x1x1",
"1x2x1",
"2x1x1",
);
// sort the array (note: usort is per reference)
usort($values, 'sortByDimension');
print_r($values);