2

次のような配列が与えられた場合:

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

約 3000 の単数形と複数形のペアで構成されていますが、単数形 (キー) を最も効率的に取得するには、たとえばarray_search_loosely($nouns, "men")?

次に、値が「man」の配列を受け取ることを期待しています。

私は4つの異なるアプローチを試しました:

オリジナル(関数 を使用します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;
}

2番目のアプローチ:

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_intersectを使用すると、 array ごとに通知が生成されるため、 を使用して arrayarray_uintersectも使用できるようにしました。この選択により、配列もチェックできます。$items$itemeach_in_array()$values

また、3 番目の省略可能なパラメーター$compare_keysは、この状況には関係ありませんが、この関数を使用する他の状況では関係があります。

3 番目と 4 番目のアプローチは、前述のアプローチを組み合わせたものです。この時点では、元のアプローチが依然として最速ですが、数百または数千の単語で関数を実行すると、操作に数十秒かかります。この状況で単数形の複数形を取得するパフォーマンスを向上させる方法について何か提案はありますか?

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 クエリにはさらに時間がかかるため、そうであると思います。私の他の唯一の提案は、辞書を管理できる数の配列に分割することです (おそらくアルファベット文字ごとに数十個)。それ以外の場合は、既存の辞書配列またはフラット ファイルからこれらを生成するスクリプトを記述し、次に AJAX を実装します。 Google の予測検索に似ていますが、検索文字列を入力すると可能な結果が表示される代わりに、検索する配列がバックグラウンドで静かに絞り込まれます。これを行うスクリプトがどこかにあり、これが実行可能であると思われる場合はそれを掘り下げることができます。基本的に、キーワードごとに辞書全体を検索する代わりに (私は 1,200 万語を超える単語を見たことがあります!)、キーワードが入力され、送信され、処理されるまでに、ループ サイクルがはるかに少なくなる可能性があります。ハードウェアも思い浮かびます。サーバーのハードディスク、プロセッサ、およびメモリの速度が、方程式の大部分を占めます。また、C++ は辞書検索にはるかに適しており、PHP 開発者にとってあまりなじみのない選択肢ではないと聞いています。ハードウェアも思い浮かびます。サーバーのハードディスク、プロセッサ、およびメモリの速度が、方程式の大部分を占めます。また、C++ は辞書検索にはるかに適しており、PHP 開発者にとってあまりなじみのない選択肢ではないと聞いています。ハードウェアも思い浮かびます。サーバーのハードディスク、プロセッサ、およびメモリの速度が、方程式の大部分を占めます。また、C++ は辞書検索にはるかに適しており、PHP 開発者にとってあまりなじみのない選択肢ではないと聞いています。

于 2013-04-13T19:58:23.967 に答える