Python fermuar gibi bir php işlevi var mı?

8 Cevap php

8 Cevap

Python ile benzer dizilerin bir dizi oluşturmak için bu işlevi try zip:

function zip() {
    $args = func_get_args();
    $zipped = array();
    $n = count($args);
    for ($i=0; $i<$n; ++$i) {
        reset($args[$i]);
    }
    while ($n) {
        $tmp = array();
        for ($i=0; $i<$n; ++$i) {
            if (key($args[$i]) === null) {
                break 2;
            }
            $tmp[] = current($args[$i]);
            next($args[$i]);
        }
        $zipped[] = $tmp;
    }
    return $zipped;
}

Eğer istediğiniz gibi pek çok öğe ile istediğiniz gibi bu fonksiyonu gibi birçok dizi iletebilirsiniz.

Sürece tüm diziler aynı uzunlukta olduğu gibi, ilk argüman olarak null ile array_map kullanabilirsiniz.

array_map(null, $a, $b, $c, ...);

Dizilerin bir kısa ise, bunlar geri sonucu kısa dizinin uzunluğu piton farklı olarak, en uzun uzunluğuna boş değerlere ile doldurulur.

Bu works exactly as Python's zip() function , ve PHP

function zip() {
    $params = func_get_args();
    if (count($params) === 1){ // this case could be probably cleaner
        // single iterable passed
        $result = array();
        foreach ($params[0] as $item){
            $result[] = array($item);
        };
        return $result;
    };
    $result = call_user_func_array('array_map',array_merge(array(null),$params));
    $length = min(array_map('count', $params));
    return array_slice($result, 0, $length);
};

Bu şekilde Python'un içinde diziler birleştirir zip() yapar ve kısa dizinin sonuna ulaştıktan sonra bulunan öğeleri dönmez.

Aşağıdaki:

zip(array(1,2,3,4,5),array('a','b'));

aşağıdaki sonucu verir:

array(array(1,'a'), array(2,'b'))

ve aşağıdaki gibidir:

zip(array(1,2,3,4,5),array('a','b'),array('x','y','z'));

aşağıdaki sonucu verir:

array(array(1,'a','x'), array(2,'b','y'))

Yukarıda bir kanıtı için this demonstration edin.

EDIT: tek bir argüman almak için destek eklendi (array_map farklı bu durumda davranır; teşekkürler Josiah).

Solution

Çözelti uygun zip() çok yakından ve aynı zamanda yerleşik PHP fonksiyonları kullanarak gibidir:

array_slice(
    array_map(null, $a, $b, $c), // zips values
    0, // begins selection before first element
    min(array_map('count', array($a, $b, $c))) // ends after shortest ends
);

Why not simple array_map(null, $a, $b, $c) call?

I already mentioned in my comment, ben nabnabit çözümünü (array_map(null, $a, $b, ...)), ama biraz değiştirilmiş bir şekilde (yukarıda gösterilen) lehine eğilimindedir.

Genel olarak bu:

array_map(null, $a, $b, $c);

Python'un için karşılığıdır:

itertools.izip_longest(a, b, c, fillvalue=None)

(Yerine yineleyici listesini isterseniz list() sarın). Bu nedenle, tam olarak (tüm diziler aynı uzunluğa sahip olmadıkça) zip() 'in davranışı taklit etmek için gereksinim uygun değildir.

I wrote a zip() functions for my PHP implementation of enum.
The code has been modified to allow for a Python-style zip() as well as Ruby-style. The difference is explained in the comments:

/*
 * This is a Python/Ruby style zip()
 *
 * zip(array $a1, array $a2, ... array $an, [bool $python=true])
 *
 * The last argument is an optional bool that determines the how the function
 * handles when the array arguments are different in length
 *
 * By default, it does it the Python way, that is, the returned array will
 * be truncated to the length of the shortest argument
 *
 * If set to FALSE, it does it the Ruby way, and NULL values are used to
 * fill the undefined entries
 *
 */
function zip() {
    $args = func_get_args();

    $ruby = array_pop($args);
    if (is_array($ruby))
        $args[] = $ruby;

    $counts = array_map('count', $args);
    $count = ($ruby) ? min($counts) : max($counts);
    $zipped = array();

    for ($i = 0; $i < $count; $i++) {
        for ($j = 0; $j < count($args); $j++) {
            $val = (isset($args[$j][$i])) ? $args[$j][$i] : null;
            $zipped[$i][$j] = $val;
        }
    }
    return $zipped;
}

Örnek:

$pythonzip = zip(array(1,2,3), array(4,5),  array(6,7,8));
$rubyzip   = zip(array(1,2,3), array(4,5),  array(6,7,8), false);

echo '<pre>';
print_r($pythonzip);
print_r($rubyzip);
echo '<pre>';

map_array tek bir dizi ile geçen sorunları aşmak için, gerçek bir işlev ama bir yerleşik zımbırtı değil gibi ne yazık ki "array" geçemez ... Bu işlevi iletebilirsiniz.

function make_array() { return func_get_args(); }

Bu array_combine ilgili olmalıdır gibi hissediyorum bu adamıştır:

function array_zip($a, $b) 
{
    $b = array_combine(
        $a, 
        $b  
        );  

    $a = array_combine(
        $a, 
        $a  
        );  

    return array_values(array_merge_recursive($a,$b));
}