【问题标题】:How to filter an array keeping the highest patch version in each minor version?如何过滤在每个次要版本中保持最高补丁版本的数组?
【发布时间】:2016-07-18 03:33:18
【问题描述】:

我有以下数组:

数组(174){ [0]=> 字符串(5)“3.0.3” [1]=> 字符串(5)“3.0.2” [2]=> 字符串(5)“3.0.1” [3]=> 字符串(5)“3.0.0” [9]=> 字符串(5)“2.9.5” [10]=> 字符串(5)“2.9.4” [11]=> 字符串(5)“2.9.3” [12]=> 字符串(5)“2.9.2” [13]=> 字符串(5)“2.9.1” [14]=> 字符串(5)“2.9.0” [18]=> 字符串(6)“2.8.11” [19]=> 字符串(6)“2.8.10” [20]=> 字符串(5)“2.8.9” }

我需要为唯一的前两个数字 x.x 找到最大的第三个数字。在此示例中,预期结果必须是:

3.0.3、2.9.5、2.8.11

这是我尝试过的:

foreach ($array as $key => $value) {
    $test = substr($value, 0, 3);
    $a = strtr($value, array('.' => '', ',' => ''));
    $b = (int) $a;
    $c = substr($b, 0, 2);
    $new_array = array($c);
    $result = array_unique($new_array);
    print_object($result);
}

【问题讨论】:

  • 虽然我真的很喜欢脑筋急转弯。我们希望您已经尝试过,您尝试过吗?
  • 这个功能可能有帮助:php.net/manual/en/function.explode.php
  • 是的,我正在努力解决这个问题。我试图先获取前两个值,然后进行比较,但我做不到。 foreach ($array as $key => $value) { $test = substr($value, 0, 3); $a = strtr($value, array('.' => '', ',' => '')); $b = (int)$a; $c = substr($b, 0, 2); $new_array = 数组($c); $result = array_unique($new_array) ;打印对象($结果); }
  • 使用usort()和PHP的version_compare()作为起点;然后可能是 array_walk() 来闯入主要/次要群体

标签: php arrays semantic-versioning


【解决方案1】:

首先,您必须按主要版本对版本进行分组。之后,您只需使用version_compare 函数按降序对结果组进行排序并返回每个组的第一个元素:

$versions = array("3.0.3", "3.0.2", "3.0.1", "3.0.0", "2.9.5", "2.9.4",
    "2.9.3", "2.9.2", "2.9.1", "2.9.0", "2.8.11", "2.8.10", "2.8.9"
);

$groupedVersions = array();
foreach ($versions as $version) {
    preg_match('/^\d+\.\d+/', $version, $majorVersion);
    if (!isset($groupedVersions[$majorVersion[0]])) {
        $groupedVersions[$majorVersion[0]] = array($version);
    } else {
        $groupedVersions[$majorVersion[0]][] = $version;
    }
}

$groupedVersions = array_map(function ($versions) {
    usort($versions, 'version_compare');
    return array_reverse($versions);
}, $groupedVersions);

$latestVersions = array_reduce($groupedVersions, function ($carry, $versions) {
    $carry[] = $versions[0];
    return $carry;
}, array());

echo '<pre>';
var_dump($latestVersions);
echo '</pre>';

结果是:

array(3) {
  [0]=>
  string(5) "3.0.3"
  [1]=>
  string(5) "2.9.5"
  [2]=>
  string(6) "2.8.11"
}

【讨论】:

    【解决方案2】:

    您只能使用explode() 并比较每个主要版本的最后一个值,然后构建具有主要和次要版本的关联数组:

        <?php
            $arr = array(0 => "3.0.3", 1 => "3.0.2", 2 => "3.0.1", 3 => "3.0.0", 9 => "2.9.5", 10 => "2.9.4", 11 => "2.9.3", 12 => "2.9.2", 13 => "2.9.1", 14 => "2.9.0", 18 => "2.8.11", 19 => "2.8.10", 20 => "2.8.9");
            $versions = array();
            $final = array();
            foreach ($arr as $version) {
                $explode = explode('.', $version); // split all parts
                $end = '';
                $begin = '';
                if (count($explode) > 0) {
                    $end = array_pop($explode); // removes the last element, and returns it
    
                    if (count($explode) > 0) {
                        $begin = implode('.', $explode); // glue the remaining pieces back together
                    }
                }
                if(!empty($versions[$begin])){
                    if($versions[$begin] < $end){
                        $versions[$begin] = $end;
                    }
                }else{
                    $versions[$begin] = $end;
                }
            }
            foreach($versions as $key=>$value){
                $final[] = "$key.$value";
            }
            print_r($final);
        ?>
    

    输出:

    Array
    (
        [0] => 3.0.3
        [1] => 2.9.5
        [2] => 2.8.11
    )
    

    【讨论】:

      【解决方案3】:

      在 PHP 中对数组数据进行分组时,根据分组标准生成临时键通常是最有效的。

      我将根据来自What every digit means in software version (1.7.1.0, for example)? 接受的答案使用一些版本术语

      在这种情况下,使用前两个整数(主要和次要版本)(并且它们必须由定界字符分隔以避免数据冲突)。迭代时,检查输出集合中是否存在临时键。如果没有,请添加它。如果是,请检查第三个整数(维护版本)是否大于为该主要-次要版本组存储的维护版本 - 如果是,则替换存储的主要-次要版本组的值。

      这在我下面的 sn-p 中非常简洁地执行。如果您需要对输出进行索引,请致电array_values(),否则请省略该步骤。

      代码:(Demo)

      $versions = [
          "3.0.1", "3.0.3", "3.0.2", "3.0.0",
          "2.9.4", "2.9.3", "2.9.2", "2.9.5", "2.9.1", "2.9.0",
          "2.8.1", "2.8.11", "2.8.10"
      ];
          
      foreach ($versions as $version) {
          $ints = explode('.', $version, 3);
          $tempKey = "{$ints[0]}.{$ints[1]}";
          if (!isset($result[$tempKey]) || version_compare($version, $result[$tempKey], 'gt')) { 
              $result[$tempKey] = $version;
          }
      }
          
      var_export(array_values($result));
      

      输出:

      array (
        0 => '3.0.3',
        1 => '2.9.5',
        2 => '2.8.11',
      )
      

      使用version_compare() 是比较版本的合适工具,但如果您希望对维护版本值进行简单的整数与整数比较,则可以避免使用。这将花费更多内存,因为您还需要存储一组分组的维护版本整数来进行比较。我建议只比较完整版本的字符串。

      【讨论】:

        猜你喜欢
        • 2019-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-23
        • 2014-04-04
        • 2015-05-18
        相关资源
        最近更新 更多