【问题标题】:Filter associative array to keep elements when their value is greater than their neighboring elements' values过滤关联数组以在元素的值大于其相邻元素的值时保留元素
【发布时间】:2019-08-30 11:39:39
【问题描述】:

我有一个关联数组,我需要从中创建一个新数组。我的目标是新数组的峰值。要为新数组选择一个值,它需要高于数组中的前一个值和下一个值。

我在网上搜索并找到了一个可以处理索引数组情况的函数 - 但不适用于关联数组。这是我想要的:

$array = array('a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3);
$result = array('b' => 2, 'e' => 3);

可用于索引数组的函数如下所示:

$a = array(0, 2, 1, 2, 3);
$b = array_filter($a, function($v, $k) use($a) {
  return $k > 0 && $v > $a[$k-1] && $k + 1 < count($a) && $v > $a[$k+1];
}, ARRAY_FILTER_USE_BOTH );

这个函数也不包含最后一个值。

【问题讨论】:

  • $result = array('b' => 2, 'e' => 3); - 是不正确的。代码边框项中的条件返回 false。只有 b 是正确的

标签: php arrays filtering associative-array


【解决方案1】:

如果你真的想获得边框项目,你应该改变条件。但一种方法可能是使用键数组来获取上一个和下一个项目

$array = array('a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3);
$keys = array_keys($array);

$b = array_filter($array, function($v, $k) use($array, $keys) {
  $k = array_search($k, $keys);
  return $k > 0 && $v > $array[$keys[$k-1]] && $k + 1 < count($keys) && $v > $array[$keys[$k+1]];
}, ARRAY_FILTER_USE_BOTH );

print_r($b);

【讨论】:

    【解决方案2】:

    这可以通过零次迭代函数调用来完成。

    在循环之前,通过为输入数组的键分配索引来声明查找数组 -- array_keys()

    然后在循环中使用条件回退值并在尝试访问不存在的元素时合并空值。

    1. ($i ? $array[$keys[$i - 1]] : $array[$key] - 1) 表示:如果$i 不为零,则通过当前键前一位的键访问输入数组中的值。否则,$i 等于零,这意味着没有更早的值,因此回退到当前值减一,以确保在比较中它会更小。

    2. ($array[$keys[$i + 1] ?? -1] ?? $array[$key] - 1) 表示:尝试访问查找数组中的下一个键,如果不存在,则使用负数,保证不存在。实际上,当$i 是循环中的最后一个索引时,将没有下一个键,因此再次回退到当前值减一。

    这应该总是优于任何进行迭代函数调用的脚本。

    代码:(Demo)

    $array = ['a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3];
    
    $keys = array_keys($array);
    foreach ($keys as $i => $key) {
        if ($array[$key] > ($i ? $array[$keys[$i - 1]] : $array[$key] - 1)
            && $array[$key] > ($array[$keys[$i + 1] ?? -1] ?? $array[$key] - 1)
        ) {
            $result[$key] = $array[$key];
        }
    }
    var_export($result);
    

    输出:

    array (
      'b' => 2,
      'e' => 3,
    )
    

    或者,如果您想改变输入数组,您可以在循环中调用unset() 并简单地反转条件逻辑。

    【讨论】:

      【解决方案3】:

      我在@splash58 工作。谢谢你。我自己也尝试过一些同样有效的方法 - 但我不知道哪种解决方案最有效。

      $result = array();
      $value1 = NULL;
      
      foreach (array_reverse($array) as $key => $value) {
        if ($value > $value1) {
          $result[$key] = $value;
        }
        $value1 = $value;
      }
      

      '$value1 = NULL' 有必要吗?

      【讨论】:

      • 您只比较两个值,因此对于有序数组,代码将获取所有似乎错误的值
      猜你喜欢
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多