Ben php bir çok düzey ilişkilendirilebilir dizilerin tüm anahtarlarını alabilirsiniz

3 Cevap php

Ben php çok boyutlu dizi için n seviyesi anahtarlarını almak neyin php herhangi bir yolu var mı?

İşte benim ilişkisel dizidir ve çıkış olarak ben böylece yapının kendisinden object_id için birçok iç içe düzeyleri orada olduğu gibi tuşları object_id için tüm değerlerini içeren ve olacak bir dizi istiyorum nasıl tuşları için tüm değerleri alabilirsiniz object_id?

   array
  'cart' => 
    array
      12061 => 
        array
          'object_id' => string '12061' (length=5)
          'discriminator' => string 'SimpleProductOffering' (length=21)
          'spec' => 
            array
              100012061 => 
                array
                  'object_id' => string '100012061' (length=9)
                  'discriminator' => string 'CompositeProductSpecification' (length=29)
                  'trait' => 
                    array
                      'MAIN_CPE' => 
                        array
                          'object_id' => string '1000000000015' (length=13)
                          'is_configurable' => string '0' (length=1)
                          'trait_value' => 
                            array
                              10001 => 
                                array
                                  'object_id' => string '10001' (length=5)
                                  'collateral' => 
                                    array
                                      empty
                          'collateral' => 
                            array
                              empty
          'offer_type' => null
          'price' => 
            array
              12862 => 
                array
                  'object_id' => string '12862' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      empty
                  'collateral' => 
                    array
                      empty
              12876 => 
                array
                  'object_id' => string '12876' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      0 => string '12876' (length=5)
                      1 => string '12894' (length=5)
                  'collateral' => 
                    array
                      empty
          'contained_offers' => 
            array
              empty
          'family' => 
            array
              0 => string 'TV Subscription' (length=24)
          'relationship' => 
            array
              'CHILDREN' => 
                array
                  'object_id' => string '1206102000' (length=10)
                  'min' => string '0' (length=1)
                  'max' => string '1000000' (length=7)
                  'related_offer' => 
                    array
                      0 => string '10410' (length=5)
                      1 => string '10411' (length=5)
              'REQUIREMENTS' => 
                array
                  'object_id' => string '1206104000' (length=10)
                  'min' => string '1' (length=1)
                  'max' => string '1' (length=1)
                  'related_offer' => 
                    array
                      0 => string '11950' (length=5)
                      1 => string '11990' (length=5)
              'EXCLUSIONS' => 
                array
                  'object_id' => string '1206101000' (length=10)
                  'min' => string '1' (length=1)
                  'max' => string '1' (length=1)
                  'related_offer' => 
                    array
                      0 => string '12062' (length=5)
                      1 => string '12063' (length=5)
              'ALTERNATIVES' => 
                array
                  'object_id' => string '1206105000' (length=10)
                  'min' => string '1' (length=1)
                  'max' => string '1' (length=1)
                  'related_offer' => 
                    array
                      0 => string '12263' (length=5)
              'BUNDLE_ITEMS' => 
                array
                  'object_id' => string '1206106000' (length=10)
                  'min' => string '1' (length=1)
                  'max' => string '1' (length=1)
                  'related_offer' => 
                    array
                      0 => string '12062' (length=5)
          'financial_terms' => 
            array
              'billing_period' => 
                array
                  0 => string 'QUARTERLY' (length=9)
              'payment_method' => 
                array
                  0 => string 'DIRECT_DEBIT' (length=12)
              'bill_presentation' => 
                array
                  0 => string 'PAPER' (length=5)
          'contract_constraints' => 
            array
              'min_contract_period' => int 24
              'cancellation_period' => string 'ALWAYS' (length=6)
              'notice_period' => int 3
              'rollover_period' => int 2
              'right_of_wd_period' => int 1
          'collateral' => 
            array
              empty
      10017 => 
        array
          'object_id' => string '10017' (length=5)
          'spec' => 
            array
              100010017 => 
                array
                  'object_id' => string '100010017' (length=9)
                  'discriminator' => string 'CompositeProductSpecification' (length=29)
                  'trait' => 
                    array
                      empty
          'offer_type' => null
          'price' => 
            array
              300306 => 
                array
                  'object_id' => string '300306' (length=6)
                  'price_alteration' => 
                    array
                      empty
                  'collateral' => 
                    array
                      empty
              12894 => 
                array
                  'object_id' => string '12894' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      empty
                  'collateral' => 
                    array
                      empty
              12862 => 
                array
                  'object_id' => string '12862' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      empty
                  'collateral' => 
                    array
                      empty
              12876 => 
                array
                  'object_id' => string '12876' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      0 => string '12876' (length=5)
                      1 => string '12894' (length=5)
                  'collateral' => 
                    array
                      empty
          'contained_offers' => 
            array
              0 => null
          'family' => 
            array
              empty
          'relationship' => 
            array
              'EXCLUSIONS' => 
                array
                  'object_id' => string '1001701000' (length=10)
                  'min' => string '1' (length=1)
                  'max' => string '1' (length=1)
                  'related_offer' => 
                    array
                      0 => string '11893' (length=5)
                      14 => string '12305' (length=5)
                      15 => string '12306' (length=5)
          'financial_terms' => 
            array
              'billing_period' => 
                array
                  0 => string 'MONTHLY' (length=7)
                  1 => string 'QUARTERLY' (length=9)
              'payment_method' => 
                array
                  0 => string 'DIRECT_DEBIT' (length=12)
                  1 => string 'DIRECT_DEBIT' (length=12)
              'bill_presentation' => 
                array
                  0 => string 'EMAIL' (length=5)
                  1 => string 'PAPER' (length=5)
          'contract_constraints' => 
            array
              'min_contract_period' => int 24
              'cancellation_period' => string 'ALWAYS' (length=6)
              'notice_period' => int 3
              'rollover_period' => int 2
              'right_of_wd_period' => int 1
          'collateral' => 
            array
              empty
  0 => 
    array
      11990 => 
        array
          'object_id' => string '11990' (length=5)
          'discriminator' => string 'SimpleProductOffering' (length=21)
          'spec' => 
            array
              100011990 => 
                array
                  'object_id' => string '100011990' (length=9)
                  'discriminator' => string 'CompositeProductSpecification' (length=29)
                  'trait' => 
                    array
                      empty
          'offer_type' => null
          'price' => 
            array
              12862 => 
                array
                  'object_id' => string '12862' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      empty
                  'collateral' => 
                    array
                      empty
              12876 => 
                array
                  'object_id' => string '12876' (length=5)
                  'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                  'price_alteration' => 
                    array
                      10017 => 
                        array
                          'object_id' => string '10017' (length=5)
                          'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                          'price_alteration' => 
                            array
                              empty
                          'collateral' => 
                            array
                              empty
                      12894 => 
                        array
                          'object_id' => string '12894' (length=5)
                          'discriminator' => string 'RecurringChargeProdOfferPriceCharge' (length=35)
                          'price_alteration' => 
                            array
                              empty
                          'collateral' => 
                            array
                              empty
                  'collateral' => 
                    array
                      empty
          'contained_offers' => 
            array
              empty
          'family' => 
            array
              0 => string 'CATV' (length=4)
          'relationship' => 
            array
              empty
          'financial_terms' => 
            array
              'billing_period' => 
                array
                  0 => string 'QUARTERLY' (length=9)
              'payment_method' => 
                array
                  0 => string 'DIRECT_DEBIT' (length=12)
              'bill_presentation' => 
                array
                  0 => string 'PAPER' (length=5)
          'contract_constraints' => 
            array
              'min_contract_period' => int 24
          'collateral' => 
            array
              empty

Çıktı tuşları için tüm değerleri içerecek bir dizi olmalıdır = object_id. Lütfen tavsiye?

3 Cevap

Dereleased çözümü (iç döngüler kullanır gibi) sanırım daha hızlı olacak, benim de object_id tuşları için dizi değerleri ile başa çıkabilirim. Sizin değiş tokuş ;)


function find_all($needle, array $haystack, array &$result = null) {
    // This is to initialize the result array and is only needed for
    // the first call of this function
    if(is_null($result)) {
        $result = array();
    }
    foreach($haystack as $key => $value) {
        // Check whether the key is the value we are looking for. If the value
        // is not an array, add it to the result array.
        if($key === $needle && !is_array($value)) {
            $result[] = $value;
        }
        if(is_array($value)) {
            // If the current value is an array, we perform the same
            // operation with this 'subarray'.
            find_all($needle, $value, $result);
        }
    }
    // This is only needed in the first function call to retrieve the results
    return $result;
}

Gördüğünüz gibi, sonuç dizisi (& ile gösterilir) referans olarak fonksiyonun her çağrısına verilir. Bu şekilde, bu fonksiyonun her özyinelemeli çağrı same dizi erişimi olan ve sadece find ekleyebilirsiniz.

Sen yapabilirsin:

$values = find_all('object_id', $array);

Bu dizi için bana verir:

Array
(
    [0] => 12061
    [1] => 100012061
    [2] => 1000000000015
    [3] => 10001
    [4] => 12862
    [5] => 12876
    [6] => 1206102000
    [7] => 1206104000
    [8] => 1206101000
    [9] => 1206105000
    [10] => 1206106000
    [11] => 10017
    [12] => 100010017
    [13] => 300306
    [14] => 12894
    [15] => 12862
    [16] => 12876
    [17] => 1001701000
    [18] => 11990
    [19] => 100011990
    [20] => 12862
    [21] => 12876
    [22] => 10017
    [23] => 12894
)

Ben çalışan bir diziye vermiş olursa olsun dökümü çevirmek için zaman alacak değilim çünkü benim test basit olması gerekiyordu; Bu işe yaramazsa, bir var_export test amaçlı dizinin veriniz.

Bu, ancak, array_walk_recursive() için bir iş gibi geliyor.

$coll = array();

function array_get_keys($value, $key, $c) {
    if (strcasecmp($key,'object_id')==0) {
        array_push($c[0],$value);
    }
}

array_walk_recursive($array, 'array_get_keys', array(&$coll));

Arama-time pass-by-reference onaylanmaz beri, bu tek yoldur (other than some convoluted object structure {[(2), çünkü son parametre array_walk_recursive bir dizide bir referans ]}) işleyici işlevine konteynere bir referans geçmek.

Bu kod $coll kendi anahtarı olarak 'object_id' tüm değerleri ile doldurmak gerekir. Bu array_walk_recursive() (yani geri çağırma işlevi kendileri diziler elemanları için başlatılan değil, olduğu) davranışı bilinmektedir, çünkü, 'Object_id' bir dizidir durumlarda çalışmaz.

EDIT (for great justice):

Nesne yapısı aslında kıvrık değil, bu yüzden yabancı dizi / referans yapıları kaçınmak istiyorsanız, burada bunu yapmak için nasıl:

$coll = new ArrayObject;

function array_get_keys($value, $key, $c) {
    if (strcasecmp($key,'object_id')==0) {
        $c[] = $value;
    }
}

array_walk_recursive($array, 'array_get_keys', $coll);

How it works

PHP'nin array_walk_recursive() fonksiyon her anahtar / değer çifti üzerindeki ilk parametre ve yinelenir verilen bir dizi alır. Değeri skaler ise, bazı kullanıcı tanımlı geri çağırma fonksiyonu anahtar / değer kombinasyonunu geçer; değer bir dizi olup olmadığını, ancak, daha sonra array_walk_recursive() kendisini özyinelemeli olarak arama, ve aynı şekilde davranmaya devam edecektir. Bu dizide her öğe ile döngüye kadar bu şekilde çalışacaktır.

İkinci parametre kullanmak için geri arama işlevi; Bu durumda, ben yazılı ve bir işlev (array_get_keys) ilan etti ve ikinci parametre bir dize olarak adını geçti. Böylece, fonksiyon array_walk_recursive() tarafından tescil ve idam fonksiyon bir anahtar / değer çifti işlenen her zaman olur.

Her iki örnekte de üçüncü parametre temelde biz onun davranışını değiştirmek için geri çağırma işlevine geçebilir "ekstra" bir veri parçasıdır - bu durumda, öyle ki bir dizi (veya ikinci örnekte, bir DiziNesnesi konteyner) ( a) küresel alanda tanımlı ve (b) $key == 'object_id' true olduğu tüm değerleri depolamak için kullanılır.

Bu küresel kapsamda modifiye edilebilir böylece (aksi takdirde, biz koleksiyonuna bir başvuru geçmek için tek yoldur çünkü ilk örnekte, ben, toplama değişken geçmek için sözdizimi array(&$coll) kullanın ) listesini almak için bir yol. İkinci örnekte, bir ArrayObject, bu dolaylı olarak, referans ile bu geçirilen kılan olarak $coll ilan, bu nedenle değiştirilmiş sağlamak için bir dizi içinde içeren gerek yoktur küresel kapsamı.

object_id Spl Yineleyicilerde kullanırken foreach döngü içinde kontrol için Alternatif:

class KeyFilter extends FilterIterator
{
    protected $acceptedKeys; // keys to return when iterating over the array

    public function __construct(array $keys, $iterator)
    {
        $this->acceptedKeys = $keys;
        parent::__construct($iterator);
    }

    public function accept()
    {
        // skip elements that return false when iterating
        return (in_array($this->key(), $this->acceptedKeys));
    }
}

FilterIterator uzanan altsınıflar accept() yöntemi uygulamak gerekir. foreach ile dizi üzerinde yineleme zaman içten, filtre yineleyici sizin accept yöntemini çağırın ve yöntemi yazılı sınav return false olduğu için herhangi unsurları atlamak olacaktır. FilterIterators istiflenebilir, yani bu çok esnek bir yaklaşım yapar Filtre Zinciri, birden FilterIterators birleştirebilirsiniz.

Bunu böyle kullanmak istiyorum

$yourArray = new KeyFilter(array('object_id' /* add more */),
                           new RecursiveIteratorIterator(
                               new RecursiveArrayIterator($yourArray)));

foreach($yourArray as $key => $value) {
    // will only return elements with an object_id key
    echo $key, '--', $value, PHP_EOL;
}

SplIterators Daha: