【问题标题】:PHP foreach loop returns an extra unwanted array (Wikipedia API)PHP foreach 循环返回一个额外的不需要的数组(维基百科 API)
【发布时间】:2017-01-05 05:45:07
【问题描述】:

我一直在研究这个问题,但没有找到任何解决方案。我对php也很陌生。

我的函数的目的是获取维基百科文章的用户输入(Category1)并返回其类别。下面的基本功能没有任何问题。

function get_all_categories ( ) {

        $url = $this->get_url ( 'categories' ) ;
        $url .= 'titles='.urlencode($_POST['Category1']);
        $url .= '&cllimit=500' ;        
        $data = $this->get_result ( $url ) ;

        $array = json_decode($data, true); }

城市规划的示例结果:

Array
(
[batchcomplete] => 
[query] => Array
    (
        [pages] => Array
            (
                [46212943] => Array
                    (
                        [pageid] => 46212943
                        [ns] => 0
                        [title] => Urban planning
                        [categories] => Array
                            (
                                [0] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:All Wikipedia articles written in American English
                                    )

                                [1] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Commons category with local link same as on Wikidata
                                    )

                                [2] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Pages using ISBN magic links
                                    )

                                [3] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Urban planning
                                    )

                                [4] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Use American English from April 2015
                                    )

                                [5] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Use dmy dates from April 2015
                                    )

                                [6] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Wikipedia articles needing clarification from June 2015
                                    )

                                [7] => Array
                                    (
                                        [ns] => 14
                                        [title] => Category:Wikipedia articles with GND identifiers
                                    )

                            )

                    )

            )

    )

)

当我尝试从这个数组中只提取标题值时,我的问题就开始了。我尝试使用 foreach 循环来做到这一点,这是我为多维数组找到的最简单的解决方案:

$array1 = new RecursiveIteratorIterator(
        new RecursiveArrayIterator($array),
        RecursiveIteratorIterator::SELF_FIRST);

        foreach ($array1 as $key => $value) {
            if (is_array($value) && $key == 'categories') {
                $result = array_map(function($element){return $element['title'];}, $value);

                print_r($result);
                }               
        }

我用这段代码得到的是两个数组。一个只有标题的数组(我想要的),还有一个不需要的数组(有时包括第一个标题)附加到末尾:

Array
(
[0] => Category:All Wikipedia articles written in American English
[1] => Category:Commons category with local link same as on Wikidata
[2] => Category:Pages using ISBN magic links
[3] => Category:Urban planning
[4] => Category:Use American English from April 2015
[5] => Category:Use dmy dates from April 2015
[6] => Category:Wikipedia articles needing clarification from June 2015
[7] => Category:Wikipedia articles with GND identifiers
)
Array
(
[ns] => 
[title] => C
)

这个额外的数组是我不明白的。我认为问题是由 foreach 循环引起的。我尝试在循环之外取消设置 $variable ,但没​​有帮助。如果我尝试将这些结果传递给另一个函数,额外的数组会变得特别麻烦。我怎样才能防止这种情况发生?

【问题讨论】:

    标签: php arrays foreach wikipedia-api


    【解决方案1】:

    为简单起见,您可以手动遍历数组,而不是使用RecursiveIteratorIterator

    RecursiveIteratorIteratorkill performance 用于大型数组。

    将您的提取逻辑更改为:

    $result = array();
    foreach($arr['batchcomplete']['query']['pages'] as $k => $v)
    {
        foreach($v['categories'] as $cat)
        {
            $result[] = $cat['title'];
        }
    }
    

    Working Demo

    【讨论】:

    • 完美运行。谢谢!
    【解决方案2】:

    正如@samir 所提到的,手动执行会更快,但是如果您需要一种遍历未知深度的搜索机制,您也可以使用基本的递归函数。它可能比 OOP 风格的 RecursiveArrayIterator/RecursiveIteratorIterator 快一点:

    function recurse($array,&$new)
        {
            foreach($array as $key => $value) {
                if($key == 'title' && isset($array['ns'])) {
                    if(!isset($array['pageid']))
                        $new[]  =   $value;
                }
                else {
                    if(is_array($value)) {
                        recurse($value,$new);
                    }
                }
            }
        }
    
    # Set's storage array for final titles
    $new    =   array();
    # Recurse your array
    recurse($array,$new);
    # Show stored values
    print_r($new);
    

    【讨论】:

      【解决方案3】:

      这是一个有趣的 PHP 错误组合:

      • $key == 'categories' 是非类型安全比较;数字数组键是整数,为了比较整数和字符串,PHP 将字符串转换为整数:粗略地说,它采用由数字组成的字符串的最长前缀。如果字符串根本不以数字开头,则字符串到整数转换的结果是 0
        因此您的条件将两次为真:对于 categories 子数组及其第一个子数组(带有密钥0)。提示:始终使用=== 进行比较。
      • PHP 允许对几乎所有非数组的对象(通常返回 null)使用 [](数组索引)运算符。因此,当array_map 尝试为$element = 14ns 子数组的第一个子项的ns 项)获取$element['title'] 时,这将成功并导致 null(var_dump 仅显示为空)。
      • 字符串略有不同:'foo'[$n] 是用于获取字符串的第 $n-th 字符的有效旧语法。当数组索引运算符用于具有非整数索引的字符串时,索引将转换为整数(正如我们所见,通常结果为零)。所以'Category:...'['title'] 将导致字符串'C'
        在对具有未知或不可靠结构的数组使用数组索引语法时,您应该始终不信任,并使用isset 或类似的东西来确保您的数组字段正在尝试获得存在。

      【讨论】:

        猜你喜欢
        • 2020-02-08
        • 1970-01-01
        • 1970-01-01
        • 2017-01-16
        • 2014-08-04
        • 1970-01-01
        • 2015-02-15
        • 2021-11-20
        • 1970-01-01
        相关资源
        最近更新 更多