代码之家  ›  专栏  ›  技术社区  ›  Pascal MARTIN

是否保留数组中的偶数元素?

  •  11
  • Pascal MARTIN  · 技术社区  · 16 年前

    说我有一个 $input 数组,其中包含以下内容:

    array
      0 => string 'a' (length=1)
      1 => string 'b' (length=1)
      2 => string 'c' (length=1)
      3 => string 'd' (length=1)
      4 => string 'e' (length=1)
      5 => string 'f' (length=1)
      6 => string 'g' (length=1)
      7 => string 'h' (length=1)
      8 => string 'i' (length=1)
      9 => string 'j' (length=1)
    

    我想买一个 $output 数组,该数组将包含以下内容:

    array
      0 => string 'a' (length=1)
      1 => string 'c' (length=1)
      2 => string 'e' (length=1)
      3 => string 'g' (length=1)
      4 => string 'i' (length=1)
    

    这个 $output 数组中包含的值为中的值的一半 $input ; 那些在输入中有偶数键的;第一个是保留的,第二个不是,第三个是,所以一个。。。

    (注意:键不保留;只有值才重要)


    我已经尝试了一些想法,并且已经有了一些不同的解决方案:

    第一个想法: 迭代输入数组,并将感兴趣的值复制到输出数组:

    $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
    $output = array();
    
    $nbr = count($input);
    for ($i = 0 ; $i < $nbr ; $i += 2) {
        $output[] = $input[$i];
    }
    
    var_dump(array_values($output));
    

    第二个想法: 迭代数组,然后 unset

    $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
    $output = $input;
    
    $nbr = count($input);
    for ($i = 1 ; $i < $nbr ; $i += 2) {
        unset($output[$i]);
    }
    
    var_dump(array_values($output));
    

    第三个想法: 结合使用 array_flip , range , array_diff_key , ... :

    $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
    $output = array();
    
    $keys_to_exclude = array_flip(range(1, count($input)-1, 2));
    $output = array_diff_key($input, $keys_to_exclude);
    
    var_dump(array_values($output));
    

    第四个想法: 差不多,但有 array_intersect_key

    $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
    $output = array();
    
    $keys_to_include = array_flip(range(0, count($input)-1, 2));
    $output = array_intersect_key($input, $keys_to_include);
    
    var_dump(array_values($output));
    

    还有别的想法吗?即使/特别是如果它听起来有点像黑客之类的话?

    我的目标不是获得最有效、最简单的语法;其实,这只是为了好玩,因为我很好奇^^

    如果标题没有用正确的词来描述我想要的,不要犹豫,告诉我;或者编辑它 :-)

    6 回复  |  直到 13 年前
        1
  •  15
  •   VolkerK    16 年前
    <?php
    $x = range('a', 'f');
    
    $x = array_map('array_shift', 
           array_chunk($x, 2)
         );
    
    var_dump($x);
    

    还是另一个

    <?php
    class ArrayEvenIterator extends ArrayIterator {
        public function next() {
            parent::next();
            return parent::next();
        }
    }
    
    $x = range('a', 'f');
    $x = iterator_to_array(new ArrayEvenIterator( $x ), false);
    
    var_dump($x);
    

    <?php
    $x = range('a', 'f');
    
    $x = array_filter( $x, function($e) use(&$c) { return 0===$c++%2; });
    
    var_dump($x);
    
        2
  •  2
  •   deceze    16 年前

    假设数字键:

    foreach ($array as $key => $value) {
        if ($key % 2 != 0) {
            unset($array[$key]);
        }
    }
    

    我的解决方案稍微有些疯狂,它可以保持索引连续而不重新索引;o)

    foreach ($array as $key => $value) {
        if (!($key%2)) {
            $array[$key/2] = $value;
        }
    }
    $array = array_slice($array, 0, ceil(count($array)/2));
    
        3
  •  2
  •   Community CDub    8 年前

    如果您使用的是PHP5.3或更高版本,或者安装了SPL扩展(默认情况下,您将使用PHP5),那么可以使用 FilterIterator ArrayObject 上课。

    class EvenKeysFilter extends FilterIterator
    {
        private function iseven($keyval)
        {
            return (($keyval % 2) == 0);
        }
    
        public function accept()
        {
            $keyval = $this->getInnerIterator()->key();
            return ($this->iseven($keyval));
        }
    }
    
    $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
    $inputobj = new ArrayObject($input);   
    
    $evenFilterIter = new EvenKeysFilter($inputobj->getIterator());    
    $output = iterator_to_array($evenFilterIter, false);
    
    print_r($output);
    

    VolkerK 指出 iterator_to_array() )

    哪一个输出正确:

    Array
    (
        [0] => a
        [1] => c
        [2] => e
        [3] => g
        [4] => i
    )
    
        4
  •  0
  •   Amber    16 年前

    不一定是最有效的方法,但既然你提到这不一定是一个要求。。。

    翻转,过滤,然后翻转。

    <?php
        function even($var)
        {
            return(!($var & 1));
        }
    
        $input = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', );
        $flipped = array_flip($input);
        $filtered = array_filter($flipped, 'even');
        $output = array_flip($filtered);
    ?>
    
        5
  •  0
  •   mickmackusa Tom Green    4 年前

    我将反转按位奇数检查,并使用 array_filter() array_values() )还是用经典的 foreach()

    代码:( Demo )

    $array = range('a', 'j');
    var_export(
        array_values(
            array_filter(
                $array,
                function($k) {
                    return !($k & 1);
                },
                ARRAY_FILTER_USE_KEY
            )
        )
    );
    echo "\n---\n";
    $result = [];
    foreach ($array as $index => $value) {
        if (!($index & 1)) {
            $result[] = $value;
        }
    }
    var_export($result);
    

    array (
      0 => 'a',
      1 => 'c',
      2 => 'e',
      3 => 'g',
      4 => 'i',
    )
    ---
    array (
      0 => 'a',
      1 => 'c',
      2 => 'e',
      3 => 'g',
      4 => 'i',
    )
    

    数组_过滤器()

        6
  •  -2
  •   John Carter    16 年前

    创建一个包装函数

    function getInput($i)
    {
         global $input;
         return $input[$i*2];
    }
    

    我想是最小最有效的。

        7
  •  -3
  •   scragar    16 年前
      function dropHalf($a){
         $f=0;
         foreach($a as $k=>$v)
           if($f = ! $f)
             unset($a[$k]);
         return $a;
      }