【问题标题】:Fast way to search through this php array of associative arrays快速搜索此 php 关联数组数组的方法
【发布时间】:2014-11-29 07:24:07
【问题描述】:

我有以下php数组;

array(
    (int) 0 => array(
        'records' => array(
            'id' => '25',
            'parent_id' => '1',
            'address' => '896167',
        )
    ),
    (int) 1 => array(
        'records' => array(
            'id' => '26',
            'parent_id' => '2',
            'address' => '890812',
        )
    ),
    (int) 2 => array(
        'records' => array(
            'id' => '28',
            'parent_id' => '16',
            'address' => '8A3813',
        )
    ),
    (int) 3 => array(
        'records' => array(
            'id' => '29',
            'parent_id' => '17',
            'address' => '8A3914',
        )
    )
)

假设我想找到哪个键有'id' => '29',那么在这个数组中搜索并返回正确键的快速方法是什么?在这种情况下,正确答案是 3。

编辑:有人会建议使用 foreach 循环数组还是使用 array_search 会更快?还是它们的速度差不多?

【问题讨论】:

  • 他们总是按id排序吗?
  • @Mooseman: id 是表中使用的主键。
  • 如果这不必非常复杂,只需遍历每个“对象”(带有键 0、1、2、3 的对象)。但是如果真的有很多对象,那么你应该使用快速算法。
  • 关键字最快,你的尝试在哪里?你为什么最快?
  • @Ghost:我正在尝试使用 foreach 循环。现在正在努力。实际上,很难确定一种方法是否是最快的。我有一个非常慢的查询问题。试图加快速度。

标签: php arrays search associative-array


【解决方案1】:

如果您要进行许多这样的搜索,最好创建一个反向查找数组。

也就是说,你做一次缓慢的线性工作,之后,它是一个快速的哈希(关联数组)查找。

一次:

$id2index = array();
foreach ($data as $index => $value) {
    $id2index[$value->id] = $index;
}

多次使用 - 查找给定 id 的索引:

$index = $id2index[$id];

【讨论】:

    【解决方案2】:
    foreach ($data as $key => $value) {
        if ($value['records']['id'] == '29') break;
    }
    echo $key;
    

    在线性时间内完成。

    如果您的数组是按 ID 排序的,您可以进行二进制搜索,这将在对数时间内完成。

    function binary_search($needle, $haystack) {
        $min = 0;
        $max = count($haystack);
        while ($max >= $min)
        {
            $mid = (int) (($min + $max) / 2);
            if ($haystack[$mid]['records']['id'] == $needle) return $mid;
            else if ($haystack[$mid]['records']['id'] < $needle) $min = $mid + 1;
            else $max = $mid - 1;
        }
        // $needle was not found
        return false;
    }
    
    echo binary_search('29', $data);
    

    【讨论】:

      【解决方案3】:

      你不能在你的数据结构上使用array_search()。您的 foreach 解决方案的时间复杂度为 O(n)array_search() 也是如此)。

      您说记录是按其 id 排序的。然后你就可以使用binary search 了,它使用O(log(n)) 会更好。

      【讨论】:

        【解决方案4】:

        您可以像这样使用二进制搜索算法:

        $searchableArray = array(
                            0 => array(
                                'records' => array(
                                    'id' => '25',
                                    'parent_id' => '1',
                                    'address' => '896167',
                                )
                            ),
                            1 => array(
                                'records' => array(
                                    'id' => '26',
                                    'parent_id' => '2',
                                    'address' => '890812',
                                )
                            ),
                            2 => array(
                                'records' => array(
                                    'id' => '28',
                                    'parent_id' => '16',
                                    'address' => '8A3813',
                                )
                            ),
                            3 => array(
                                'records' => array(
                                    'id' => '29',
                                    'parent_id' => '17',
                                    'address' => '8A3914',
                                )
                            )
                        );
        
        $foundKey = findKey( $searchableArray, 29 );
        echo "Found key: " . $foundKey;
        
        function findKey( $searchableArray, $key ){
            $splittedArray = splitArray( $searchableArray );
            if( isInLeftChunk( $splittedArray[0], $key ) ){
                if( ! isOnlyElement( $splittedArray[0] ) ){
                    return findKey( $splittedArray[0], $key );
                }
                return key( $splittedArray[0] );
            }
            elseif( isInRightChunk( $splittedArray[1], $key ) ){
                if( ! isOnlyElement( $splittedArray[1] ) ){
                    return findKey( $splittedArray[1], $key );
                }
                return key( $splittedArray[1] );
            }
        
            // Element not found
            return false;
        }
        
        function isOnlyElement( $arrayChunk ){
            return count( $arrayChunk ) == 1;
        }
        
        function isInLeftChunk( $arrayChunk, $key ){
            end( $arrayChunk );
            $latestKey = key( $arrayChunk );
            if( is_int( $latestKey )){
                return $arrayChunk[ $latestKey ]['records']['id'] >= $key;
            }
            return $arrayChunk[ $latestKey ]['id'] >= $key;
        }
        
        function isInRightChunk( $arrayChunk, $key ){
            reset( $arrayChunk );
            $firstKey = key( $arrayChunk );
            if( is_int( $firstKey )){
                return $arrayChunk[$firstKey]['records']['id'] <= $key;
            }
            return $arrayChunk[ $firstKey ]['id'] <= $key;
        }
        
        function splitArray( $unsplittedArray ){
            $arrayLenght = count( $unsplittedArray );
            if( $arrayLenght == 1 ){
                return array_chunk( $unsplittedArray, $arrayLenght, true );
            }
        
            $odd = $arrayLenght % 2 != 0;
            if( $odd ){
                $arrayLenght += 1;
            }
            $arrayLenght = $arrayLenght * 0.5;
        
            return array_chunk( $unsplittedArray, $arrayLenght, true );
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-12
          • 2019-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-13
          相关资源
          最近更新 更多