2

给定一个数组,如:

$nouns = array(
    "man" => array("men"),
    "octopus" => array("octopi", "octopuses"),
    "ox" => array("oxen")
);

由大约 3000 个单复数对组成,例如,如何通过调用最有效地获得单数(键)array_search_loosely($nouns, "men")

然后我希望收到一个值为“man”的数组。

我尝试了四种不同的方法:

原创(使用功能array_is_assoc,这是不言自明且与情况无关的)

function array_search_loosely($array, $values, $compare_keys = false) {
  $values = is_array($values) ? $values : array($values);
  foreach($array as $item_key => $item) {
    if (is_array($item)) {
      $return_key = true;
      foreach($values as $value_key => $value) {
        if (!in_array($value, $item)) {
          $return_key = false;
          break;
        }
        elseif($compare_keys === true and array_is_assoc($values)) {
          if (!in_array($value_key, array_keys($item, $value))) {
            $return_key = false;
            break;
          }
        }
      }
      if ($return_key === true) {
        $item_keys[] = $item_key;
      }
    }
    elseif(!is_array($values)) {
      if ($item === $values) {
        $item_keys[] = $item_key;
      }
    }
  }
  return (isset($item_keys))? $item_keys : false;
}

第二种方法

function array_search_loosely($array, $values, $compare_keys = false) {
    $keys = array_keys(array_filter($array, function($item) use ($values, $compare_keys) {
        return (!is_array($item) and $item === $values) or (is_array($item) and each_in_array($item, array_create($values), $compare_keys));
    }));
    return !empty($keys) ? $keys : false;
}

function each_in_array($array, $values, $compare_keys = false) {
    return $compare_keys === false ? count(array_uintersect($values, $array, function($item1, $item2) { return $item1 === $item2 ? 0 : ($item1 > $item2 ? 1 : -1); })) == count($values) : count(array_uintersect_assoc($values, $array, function($item1, $item2) { return $item1 === $item2 ? 0 : ($item1 > $item2 ? 1 : -1); })) == count($values);
}

我选择使用array_uintersect, 也允许数组$items,因为如果我要使用 array_intersect,将为每个数组生成通知$item。此选项也允许each_in_array()检查数组$values

此外,第三个可选参数$compare_keys与这种情况无关,但在我使用该函数的其他情况下。

第三种和第四种方法是前一种方法的混合。在这一点上,我原来的方法仍然是最快的,但是当我在几百或几千个单词上运行我的函数时,操作仍然会花费几十秒。关于如何提高在这种情况下获得复数单数的性能的任何建议?

4

3 回答 3

0

输出:

输出 资源:

<!DOCTYPE html>
<html>
    <body>
        <?php
            $nouns = array  (
                                "data" => array("data"),
                                "datum" => array("data"),
                                "man" => array("men"),
                                "octopus" => array("octopi", "octopuses"),
                                "ox" => array("oxen"),
                                "hippopotamus" => array("hippopotami", "hippopotamuses")
                            );

            function find_singular($nouns, $search)
            {
                foreach($nouns as $noun => $values)
                {
                    if(in_array($search, $values))
                    {
                        $found[] = $noun;
                    }
                }
                if(!empty($found))
                {
                    $n = count($found);
                    if($n > 1)
                    {
                        echo "<strong>$search</strong> has $n singular forms: <em>";
                        print_r(implode('</em> and <em>', $found).'</em><br />');
                    }
                    else
                    {
                        echo "<b>$search</b> is the plural of <em>$found[0]</em><br />";
                    }
                }
                else
                {
                    echo "<b>$search</b> was not found.<br />";
                }
            }

            find_singular($nouns, "men");
            find_singular($nouns, "octopi");
            find_singular($nouns, "data");
            find_singular($nouns, "oxen");
            find_singular($nouns, "octopuses");
            find_singular($nouns, "hippopotami");
            find_singular($nouns, "kittens");
        ?>
    </body>
</html>

希望这可以帮助!

编辑:这样做的目的是什么?我猜您正在为 Web 或应用程序界面创建字典应用程序。只要您打算实现搜索功能,我认为您将无法避免循环。您是否将整个字典存储在 PHP 数组中?我假设您是因为 XML 和 mysql 查询会花费更多时间。我唯一的其他建议是将字典拆分为您可以管理的尽可能多的数组(每个字母可能有几十个),或者编写一个脚本从现有的字典数组或平面文件中生成这些,然后在您的搜索框,类似于谷歌的预测搜索,但不是在输入搜索字符串时显示可能的结果,而是在后台默默地缩小要搜索的数组。我在某处有一个脚本可以执行此操作,如果这听起来可行,可以将其挖掘出来。基本上,不是搜索整个字典(我见过一个超过 1200 万字的字典!),在键入、发送和处理关键字时,循环周期可能会少得多。硬件也浮现在脑海中——服务器的硬盘、处理器和内存速度将占大部分。我还听说 C++ 更适合字典搜索,对于 PHP 开发人员来说不会太陌生。硬件也浮现在脑海中——服务器的硬盘、处理器和内存速度将占大部分。我还听说 C++ 更适合字典搜索,对于 PHP 开发人员来说不会太陌生。硬件也浮现在脑海中——服务器的硬盘、处理器和内存速度将占大部分。我还听说 C++ 更适合字典搜索,对于 PHP 开发人员来说不会太陌生。

于 2013-04-13T19:58:23.967 回答
0
$search = 'men';
$found  = '';

foreach($nouns AS $noun => $values){
   if(in_array($search, $values){
        echo 'Found what we\'re looking for.';
        $found = $nouns[$noun];
   }

}

print_r($found);
于 2013-04-13T17:08:11.930 回答
0

您当前格式的地图不适合进行查找。您还需要反转它:

$invert = array(
  'men' => 'man',
  'octopi' => 'octopus',
  'octopuses' => 'octopus',
  'oxen' => 'ox',
);
于 2013-04-13T16:35:39.827 回答