0

php中有什么方法可以在php中获取多维数组的n级键吗?

这是我的关联数组,作为输出,我想要一个包含键的所有值的数组,object_id因为你可以从结构本身那里有许多嵌套级别object_id,那么我怎样才能获得键的所有值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

输出应该是一个数组,其中包含 keys = 的所有值object_id。好心提醒 ?

4

5 回答 5

7
$res = array();
foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($arr), RecursiveIteratorIterator::SELF_FIRST) as $k => $v) {
    if ($k === 'object_id') {
        $res[] = $v;
    }
}
于 2010-02-02T21:55:46.180 回答
5

我猜 Dereleased 的解决方案会更快(因为它使用内部循环),我的也可以处理object_id键的数组值。你的权衡;)


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

如您所见,函数的每次调用都会将结果数组作为引用(用 表示&)。这样,这个函数的每个递归调用都可以访问同一个数组,并且可以添加一个查找。

你可以做:

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

它给了我你的数组:

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
)
于 2010-02-02T21:11:10.630 回答
3

我的测试必须简单,因为我不会花时间将您提供的任何转储转换为工作数组。如果这不起作用,请提供一个var_export用于测试目的的数组。

然而,这听起来像是array_walk_recursive().

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

to的最后一个参数array_walk_recursive是数组中的引用,因为由于不推荐使用调用时传递引用,这是将容器引用传递给处理程序的唯一方法(除了一些复杂的对象结构 见下文)功能。

此代码应填充$coll以“object_id”为键的所有值。它不适用于“object_id”是数组的情况,因为这是已知的行为array_walk_recursive() (即,回调函数不会为本身是数组的元素启动)。

编辑(为了伟大的正义):

对象结构实际上并没有那么复杂,所以如果你想避免多余的数组/引用结构,这里是如何做到的:

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

这个怎么运作

PHP 的array_walk_recursive()函数将给定数组作为其第一个参数,并遍历每个键/值对。如果值是标量,它将键/值组合传递给一些用户定义的回调函数;但是,如果该值是一个数组,array_walk_recursive()则将递归调用自身,并继续以相同的方式运行。它将以这种方式工作,直到它遍历数组中的每个元素。

第二个参数是要使用的回调函数;在这种情况下,我编写并声明了一个函数 ( array_get_keys),并将其名称作为字符串传递给第二个参数。因此,该函数被注册array_walk_recursive()并且是每次处理键/值对时执行的函数。

两个示例中的第三个参数基本上是一段“额外”数据,我们可以传递给回调函数以改变其行为——在本例中,它是一个数组(或在第二个示例中,是一个 ArrayObject 容器),即 ( a) 在全局范围内定义和 (b) 用于存储所有$key == 'object_id'为真的值。

在第一个示例中,我使用语法array(&$coll)来传递集合变量,因为这是传递对集合的引用的唯一方法,以便可以在全局范围内对其进行修改(否则,我们无法检索列表) . 在第二个示例中,我声明$coll为 an ArrayObject,这使其通过引用隐式传递,因此无需将其包含在数组中以确保在全局范围内对其进行修改。

于 2010-02-02T21:12:27.307 回答
1

使用 Spl 迭代器时object_id在循环中检查的替代方法:foreach

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 的子类必须实现该accept()方法。在内部,当使用 迭代您的数组时foreach,过滤器迭代器将调用您的accept方法并跳过在该方法中编写的测试将返回 false 的任何元素。FilterIterator 是可堆叠的,因此您可以将多个 FilterIterator 组合到一个 Filter Chain 中,这使得这是一种非常灵活的方法。

你会这样使用它

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

更多关于拆分器的信息:

于 2010-02-02T22:10:35.317 回答
0

基于@goat的回答,我写了一个小函数:

  • 在多维数组中通过键查找值(无论级别如何)
  • 排除空值
  • 如果需要,删除重复项
  • false如果为空则返回

功能 :

function array_find_recursive($arr, $key, $unique = false) {
    
    $res = false;

    foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($arr), RecursiveIteratorIterator::SELF_FIRST) as $k => $v) {
        if ($k === $key && $v != "") {
            $res[] = $v;
        }
    }
    
    if($unique)
        return array_unique($res);
    
    return $res;
}

无论重复使用:

$result = array_find_recursive($my_array, 'key');

使用排除重复项:

$result = array_find_recursive($my_array, 'my_key', true);
于 2021-06-14T09:38:59.050 回答