对表示尺寸的值前缀进行自定义排序(XXS、XS、S、M、L、XL、XXL)

问题描述 投票:0回答:4

我目前正在尝试对属于数组的一些服装尺寸数组(S M L XL XXL 等)进行排序。我可以通过以下函数来做到这一点(感谢这个地方Php Array Sorting Clothing Sizes (XXS XS S M L XL XXL) and Numbers on a Dynamic Array):

function cmp($a, $b) {
    
        $sizes = array(
        "XXS" => 0,
        "XS" => 1,
        "S" => 2,
        "M" => 3,
        "L" => 4,
        "XL" => 5,
        "XXL" => 6
        );
        
        $asize = $sizes[$a];
        $bsize = $sizes[$b];
        
        if ($asize == $bsize) {
            return 0;
        }
        
        return ($asize > $bsize) ? 1 : -1;
        
    }
    
    usort($the_array, "cmp");

对于如下所示的数组来说,这一切都很好:$the_array("S", "M", "XL")。 但是,我的数组看起来有点像这样:

$the_array = [
    "S : price £10",
    "XXL : price £10",
    "M : price £10",
    "XS : price £10"
];

这使得它不起作用。我需要一个函数,理想情况下只查看数组的第一部分直到“:”。

php arrays sorting custom-sort
4个回答
2
投票

此解决方案将在每个字符串的开头搜索大小值。仅当尺寸不是另一个尺寸的前缀时,它才有效,例如“X”将是“XL”的前缀。它不依赖于数据的特定格式;它将找到最早出现的有效大小字符串。

// Your comparison function:
function cmp($a, $b) {
  // Make the array static for performance.
  static $sizes = array('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL');

  // Find the size of $a and $b (the first string for which strpos===0)
  $asize = 100; // Sort non-size strings after matching sizes.
  $apos = -1;
  $bsize = 100;
  $bpos = -1;
  foreach ($sizes AS $val => $str) {
    // It's important to use `===` because `==` will match on
    // FALSE, which is returns for no match.
    if (($pos = strpos($a, $str)) !== FALSE && ($apos < 0 || $pos < $apos)) {
      $asize = $val;
      $apos = $pos;
    }
    if (($pos = strpos($b, $str)) !== FALSE && ($bpos < 0 || $pos < $bpos)) {
      $bsize = $val;
      $bpos = $pos;
    }
  }

  return ($asize == $bsize ? 0 : ($asize > $bsize ? 1 : -1));
}

usort($the_array, 'cmp');

1
投票

适用于任意数量的 X。

function cmpSizes($a, $b) {
    list($a, $b) = array(strtolower($a), strtolower($b));
    $weights = array('s' => 1, 'm' => 2, 'l' => 3);
    $primaryWeights = array();
    foreach(array('a', 'b') as $var) {
        if(is_numeric(strpos($$var, 's'))) {
            $weight = $weights['s'];
        } elseif(is_numeric(strpos($$var, 'm'))) {
            $weight = $weights['m'];
        } elseif(is_numeric(strpos($$var, 'l'))) {
            $weight = $weights['l'];
        } else {
            return -1;
        }
        $primaryWeights[$var] = $weight;
    }
    if($primaryWeights['a'] === $primaryWeights['b']) {
        $xCt = array('a' => substr_count($a, 'x'), 'b' => substr_count($b, 'x'));
        if($xCt['a'] > $xCt['b']) {
            return $primaryWeights['a'] === $weights['s'] ? -1 : 1;
        } elseif($xCt['a'] < $xCt['b']) {
            return $primaryWeights['a'] === $weights['s'] ? 1 : -1;
        }
        return 0;
    } elseif ($primaryWeights['a'] > $primaryWeights['b']) {
        return 1;
    }
    return -1;
}

示例代码

$userSizes = array('XS','S','XXXXS','XXL','L','M','XL');
usort($userSizes, 'cmpSizes');
var_dump($userSizes);

产量

array(7) {
  [0] =>
  string(5) "XXXXS"
  [1] =>
  string(2) "XS"
  [2] =>
  string(1) "S"
  [3] =>
  string(1) "M"
  [4] =>
  string(1) "L"
  [5] =>
  string(2) "XL"
  [6] =>
  string(3) "XXL"
}

0
投票

调用

usort()
并在其回调中使用
explode()
将允许您对第一部分进行排序。

$sizes = array(
    "XXS" => 0,
    "XS" => 1,
    "S" => 2,
    "M" => 3,
    "L" => 4,
    "XL" => 5,
    "XXL" => 6
    );
$the_array = array("S : price £10", "XXL : price £10", "M : price £10", "XS : price £10");

// Anonymous function -- PHP 5.3+ only...
// Uses the $sizes array from the higher scope...
usort($the_array, function($a, $b) use ($sizes) {
  // Split each on space,colon,space
  list($asize, $aprice) = explode(' : ', $a);
  list($bsize, $bprice) = explode(' : ', $b);

  // Perform the usort comparison
  // which uses the sizes matched above as array keys to the $sizes array
  if ($sizes[$asize] == $sizes[$bsize]) {
    return 0;
  }
  return $sizes[$asize] < $sizes[$bsize] ? -1 : 1;
});

// Output:
var_dump($the_array);
array(4) {
  [0] =>
  string(15) "XS : price £10"
  [1] =>
  string(14) "S : price £10"
  [2] =>
  string(14) "M : price £10"
  [3] =>
  string(16) "XXL : price £10"
}

如果分隔符并不总是如上所述的

space,colon,space
并且有所不同,则需要使用
preg_split()
而不是
explode()

// Split on any number of spaces surrounding the :
list($asize, $aprice) = preg_split('/\s*:\s*/', $a);

0
投票

如果您只想按大小对数组进行排序,则可以执行以下操作:

/** THE SORT FUNCTION **/
function sortSize($data_arr)
{
    $sizes_arr = array('XXS' => 0, 'XS'  => 1, 'S'   => 2, 'M'   => 3, 'L'   => 4, 'XL'  => 5, 'XXL' => 6);

    $data_sort_arr = array();
    foreach ($data_arr as $value)
    {
        //get the size
        $size_item_arr = explode(':', $value);
        $size_item_str = trim($size_item_arr[0]);

        //get the position of size from sizes array
        $size_pos_int = intval($sizes_arr[$size_item_str]);

        //populate new array with sorted data
        $data_sort_arr[$size_pos_int] = $value;
    }

    //sort then reset keys numerically
    ksort($data_sort_arr);
    return array_values($data_sort_arr);
}
/** THE SORT FUNCTION **/

/** THE TEST **/
$data_arr = array("S : price £10", "XXL : price £10", "M : price £10", "XS : price £10");    
print_r(sortSize($data_arr));
/** THE TEST **/

我得到了以下结果:

Array
(
    [0] => XS : price £10
    [1] => S : price £10
    [2] => M : price £10
    [3] => XXL : price £10
)

我希望这就是您所需要的?!

干杯。

© www.soinside.com 2019 - 2024. All rights reserved.