【问题标题】:How to prioritize strpos to find me the most accurate result如何确定 strpos 的优先级以找到最准确的结果
【发布时间】:2018-05-09 16:24:08
【问题描述】:

我有一个数组:

$array_of_routes = ['users/', 'articles/more', 'users/get', 'homepage/'];

而且,例如我有一个字符串:

$route = "users/get/1"; 

所以我尝试通过使用 strpos 来找到它,但因为“users/”在 $array_of_routes 中是“users/get”的头部,所以我得到的是“users/”而不是“users/get”,这是这是有道理的,因为这就是我要求代码做的事情。

但是在尝试在字符串中查找子字符串时,有没有办法优先排序或使结果更准确?

注意:从数组中删除 'users/' 时,我会得到 'users/get'

这是我的代码:

foreach($array_of_routes as $uri){
  if(strpos($current_uri, $uri) !== false)
    return $uri;

}

感谢您的帮助!

【问题讨论】:

  • 将匹配项按最长排序。
  • 您的路线上是否可以选择尾随斜杠?
  • @MonkeyZeus 是的,可以选择!
  • @user2561521 我明白了,请查看我的回答。

标签: php arrays string sorting strpos


【解决方案1】:

您需要拆分$route 并将其与$array_of_routes 中可用的最高特异性匹配

<?php
$array_of_routes = ['users', 'articles/more/', 'users/get', 'homepage'];
$route = "users/get/1/fgd/d/fg/";

// No reason to have trailing nor leading slashes or spaces; they are just noise
$array_of_routes = array_map(function($v){return trim(trim($v, '/'));}, $array_of_routes );
$route = trim(trim( $route, '/' ));

// Get the requested route pieces
$route_pieces = explode('/', $route);

// Make sure we loop enough times to account for all of the pieces
for($i = 0; $i<count($route_pieces); ++$i)
{
    // With each loop, build the route with one piece less and check if it exists in $array_of_routes
    if(in_array(implode('/', array_slice($route_pieces, 0, (count($route_pieces)-$i))), $array_of_routes))
    {
        echo 'Most specific route: '.implode('/', array_slice($route_pieces, 0, (count($route_pieces)-$i)));
        echo 'Arguments: '.implode('/', array_slice($route_pieces, (count($route_pieces)-$i)));
        break;
    }
}

$route = "users/get/1/fgd/d/fg/"; 的输出:

Most specific route: users/get
Arguments: 1/fgd/d/fg

【讨论】:

    【解决方案2】:

    鉴于此

    字符串前缀相同的2条路由A和B可以是同一级别也可以是不同级别

    示例1)同级(前缀=/users/):

    /users/get
    /users/post
    

    示例2)不同级别(前缀=/users):

    /users/get
    /users
    

    我们可以这样说:

    以“最长优先”的顺序存储路线,您将获得以下语句: 具有相同字符串前缀和不同级别的 2 条路由总是首先存储更具体的级别。

    获取方式:

    $array_of_routes = ['users/', 'articles/more', 'users/get', 'homepage/', ...];
    
    function sort_by_length($a,$b){
      return strlen($b)-strlen($a);
    }
    
    usort($array_of_routes,'sort_by_length');
    
    function findRoute($current_uri){
      foreach($array_of_routes as $uri){
        if(strpos($current_uri, $uri) === 0){
          return $uri;
        }
      }
    }
    

    注意:strpos 函数必须返回 0,否则你会发现一些错误的路由匹配你的 uri。

    【讨论】:

      【解决方案3】:

      简单! 对数组进行排序,使 users/get 位于 users/ 前面。做一个$array_of_routes = rsort($array_of_routes);

      这会将较长的匹配项放在首位,如果最长的项目匹配,则函数返回。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多