Bir dizinin bile sayılı unsurları tutulması?

6 Cevap php

Ben böyle bir şey içeren bir $input dizi var ki:

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)

Ben bu içerecek bir $output dizisini almak istiyorum:

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 dizisi $input vardı yarım değerlerini içerir; Hatta giriş anahtarları sayılı olduğu olanlar; ilk üçte biri, ikinci bir değil, tuttu, ve böylece biridir ...

(Note: the keys are not preserved ; only the values are important)

How could I do that ? Keeping only one on two values of the array ?


Zaten bazı fikirler denedim, ve zaten bir kaç farklı çözümleri var adres:

First idea: giriş dizideki üzerinde yineleme ve çıkış diziye ilginç değerleri kopyalayın:

$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));

Second idea: dizinin üzerinde yineleme, ve unset ne tutmak istemiyorum:

$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));

Third idea:, array_flip, range, array_diff_key bir combinaison kullanımı ...:

$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));

Fourth idea: aynı şey hakkında, fakat 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));

Başka herhangi bir fikir? Bu tür hacky ya da bir şey gelse / özellikle?

My goal is not to get the most efficient nor simple syntax ; it's just for fun and because I am curious, actually ^^

If the title is not using the right words to describe what I want, don't hesitate to tell ; or edit it :-)

6 Cevap

<?php
$x = range('a', 'f');

$x = array_map('array_shift', 
       array_chunk($x, 2)
     );

var_dump($x);

ya da başka bir

<?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);

veya bir php 5.3 kapanması ile (ki bu durumda küresel daha iyi ;-) değil)

<?php
$x = range('a', 'f');

$x = array_filter( $x, function($e) use(&$c) { return 0===$c++%2; });

var_dump($x);

Sayısal tuşları varsayarsak:

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


EDIT

İşte yeniden indeksleme olmadan sürekli dizini tutar benim biraz daha deli bir çözüm gider. , O)

foreach ($array as $key => $value) {
    if (!($key%2)) {
        $array[$key/2] = $value;
    }
}
$array = array_slice($array, 0, ceil(count($array)/2));

Eğer (sizden PHP 5 üzerinde varsayılan olarak) PHP 5.3 veya üstü ya da SPL uzatma yüklü kullanıyorsanız, size FilterIterator ve ArrayObject sınıflarını kullanabilirsiniz.

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);

(Işaret için VolkerK için aksesuvar iterator_to_array() )

Hangi doğru bu çıkışlar:

Array
(
    [0] => a
    [1] => c
    [2] => e
    [3] => g
    [4] => i
)

İlle en etkili yöntem, ama bunu mutlaka bir gereklilik değildi belirtilen beri ...

, filtre çevirmek, sonra geri çevirmek.

<?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);
?>

sarıcı işlev oluşturmak

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

En küçük ve en verimli ben tahmin.

  function dropHalf($a){
     $f=0;
     foreach($a as $k=>$v)
       if($f = ! $f)
         unset($a[$k]);
     return $a;
  }

Ben kapalı düşünebildiğim en küçük versiyonu.