【问题标题】:PHP - Sort array with sizes XXS-XXL and other valuesPHP - 对大小为 XXS-XXL 和其他值的数组进行排序
【发布时间】:2015-05-26 16:02:34
【问题描述】:

我在动态创建的数组 $product_sizes 中有这些类型的值:

类型 1(带字符的数值): 45 cm、120 cm、50x70 cm、100 x 160 cm、10 mm x 30 cm

Type 2(衣服尺码): XXS、XS、S、M、L、XL、XXL

类型 3(文本,当前不在数组中,最好将其包含在解决方案中以备将来证明): 大,小,...


我有此代码可用于对 Type 1 值进行排序

function sort_numeric($a, $b) {
  return $a - $b;
}
usort($product_sizes, 'sort_numeric');

此代码用于排序 Type 2 XXS-XXL 尺寸 (found on stackoverflow)

function sort_size($a, $b) {
  static $sizes = array('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL');

  $asize = 100;
  $apos = -1;
  $bsize = 100;
  $bpos = -1;
  foreach ($sizes AS $val => $str) {
    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($product_sizes, 'sort_size');

我不知道如何组合此代码以适用于两种(或所有 3 种)类型的值。

该数组是根据所选产品动态创建的,并且每次只有一种类型的值。

类型 1 的值应按其数值排序(省略厘米、毫米或其他单位),例如:

  1. 10 毫米 x 30 厘米
  2. 45 厘米
  3. 50x70 厘米
  4. 100 x 160 厘米
  5. 120 厘米

【问题讨论】:

  • 您可能需要考虑使用正则表达式来检测它属于哪个类型。例如,您可以检查元素是否至少有一个数字,以了解它肯定属于第一组,如果没有,则它属于第二组。你能给我们举一个第三种类型的例子吗? (一个简单的正则表达式,如'~([0-9]+|[0-9])~' 就足够了)
  • 感谢@briosheje 对正则表达式的提示,我已经用正则表达式创建了条件,然后执行排序。看来现在可以了:)

标签: php arrays sorting


【解决方案1】:

假设您的排序功能确实有效,并假设我对正则表达式真的很不好,我已经实现了一个可以为您完成这项工作的类:

<?php
class sorter {

    private $_array = array();

    function __construct($array) {
        $this->_array = $array;
    }

    public function elaborate() {
        if (preg_match("~([0-9]+|[0-9])~", $this->_array[0])) {
            usort ($this->_array, array('sorter','sort_numeric'));
        }
        else {
            if (preg_match("~(?=^(X)(?=(L)$))|(?=^(L)$)|(?=^(M)$)~", $this->_array[0])) {
                usort ($this->_array, array('sorter','sort_size'));
            }
            else {
                usort ($this->_array, array('sorter','sort_text'));
            }
        }
        return $this->_array;
    }

    protected static function sort_numeric($a, $b) {
      return $a - $b;
    }

    protected static function sort_size($a, $b) {
      static $sizes = array('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL');

      $asize = 100;
      $apos = -1;
      $bsize = 100;
      $bpos = -1;
      foreach ($sizes AS $val => $str) {
        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));
    }

    protected static function sort_text($a, $b) {
        static $sizes = array("extra small","small","quite small?","something a bit too small","you surely don't fit there.","medium","big","very big","huge","enormous!");

        $asize = 100;
        $apos = -1;
        $bsize = 100;
        $bpos = -1;
          foreach ($sizes AS $val => $str) {
            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));
    }
}
?>

对于你说的“类型 3”,它基本上和类型 2 完全一样,你只需要实现一个包含文本应该包含的元素的数组。

上面代码的用法,下面3个例子:

<?php
$type1 = array("120 cm","100 x 160 cm","10 mm x 30 cm");
$type2 = array("XL","XS","XXL","M");
$type3 = array("very big","small","extra small","something a bit too small");

$sorter = new sorter($type1);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";

$sorter = new sorter($type2);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";

$sorter = new sorter($type3);
echo "<pre>";
print_r($sorter->elaborate());
echo "</pre>";
?>

输出:

Array
(
    [0] => 10 mm x 30 cm
    [1] => 100 x 160 cm
    [2] => 120 cm
)
Array
(
    [0] => XS
    [1] => M
    [2] => XL
    [3] => XXL
)
Array
(
    [0] => extra small
    [1] => small
    [2] => something a bit too small
    [3] => very big
)

这背后的逻辑很简单:

第一个正则表达式检查数组的第一个元素内是否有任何数字。如果是这样,它会使用 sort_numeric 函数对其进行排序。

第二个正则表达式检查数组的第一个元素是以 X 开头并以 L 结尾还是以 M 或 L 开头并以 M 或 L 结尾(如果我没记错的话,这应该涵盖大多数情况):如果是, 它使用 sort_size 函数,否则使用 sort_text。

工作沙箱:

http://sandbox.onlinephpfunctions.com/code/9362377a481b0f4f2d33ccdfa4347f4e7c005e92

【讨论】:

  • 感谢详尽的回答,因为我真的是一个 php 菜鸟,我无法正确实现它:/ 但是我找到了一个带有条件和正则表达式的解决方案......
  • @Mirek:这正是我在那里所做的;)如果您想保留您的代码以进行进一步编辑(您知道,您永远不会知道有一天您是否需要以其他方式进行排序)我强烈建议您使用类和对象,这样更容易使用它们,并且将来更容易维护和优化您自己的代码。
  • 我又试了一次,终于可以实现你的代码,除了 sort_text 函数和正确的捷克语言环境排序。我试过protected static function sort_text($a, $b) { setlocale (LC_ALL, 'czech'); return strcoll($a, $b); },但它不起作用:/你可以在这里看到它:link。它应该按照与代码中 $type3 数组中的顺序完全相同的顺序进行排序,但是结果不同...
  • @mirek:如果它没有正确排序,那可能是因为 Windows 中的 setlocale 错误。我建议您使用 Collat​​or PHP 类,如下所示:stackoverflow.com/questions/120334/…。你需要在你的服务器上尝试,因为这样的包没有安装(或启用)在 php 在线沙箱中,因此你必须尝试在你自己的环境中运行它。为了使其正常工作,请在执行调用 sort_text 的 usort 函数之前稍微创建一个 Collat​​or 对象,并从函数中删除 setlocale ;)
  • 啊,好吧,现在我明白为什么它在 Windows localhost 测试环境中无法正常工作了。由于我无法使用 Collat​​or PHP 类,我已将语言环境更改为 cs_CZ.utf8,在 usort 之前将其移动,将其上传到服务器(linux)并且它按预期工作:) 非常感谢您的帮助;) sandbox上的工作示例
【解决方案2】:

根据 briosheje 评论的提示,我找到了解决方案。

不确定数组中的 preg_grep 搜索是否正确,但它可以工作...

$product_sizes = array();

function sort_numeric($a, $b) {
  return $a - $b;
}

function sort_size($a, $b) {
  static $sizes = array('XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL');

  $asize = 100;
  $apos = -1;
  $bsize = 100;
  $bpos = -1;
  foreach ($sizes AS $val => $str) {
    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));
}

if (preg_grep('~([0-9]+|[0-9])~', $product_sizes)) {
  usort($product_sizes, 'sort_numeric');
} else if (preg_grep('~(?=^(X+)(?=(L|S)$))|(?=^(L)$)|(?=^(M)$)|(?=^(S)$)~', $product_sizes)) {
  usort($product_sizes, 'sort_size');
} else {
  setlocale (LC_COLLATE, 'cs_CZ.utf8');
  usort($product_sizes, 'strcoll');
}

foreach ($product_sizes as $product_size_filter) {
  echo '<p>' . $product_size_filter . '</p>';
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 2017-06-15
    • 1970-01-01
    相关资源
    最近更新 更多