2013-04-13 76 views
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與此情況無關,但在其他情況下使用該功能。

第三種和第四種方法是前述的混合物。在這一點上,我的原始方法仍然是最快的,但是當我用幾百或幾千個字運行我的功能時,操作仍將花費幾十秒。關於如何提高在這種情況下獲得複數奇異性的任何建議?

+0

「然後,我期望得到與值數組的‘人’。」 - 這是至關重要的嗎?會不會有一個字符串更有用? – verbumSapienti

+0

有時兩個單數字具有相同的複數,這意味着應該返回多個鍵。 (data,datum => data)另外,這在函數的其他應用程序中尤爲重要。 – user2180613

回答

0

以當前格式顯示的地圖不適合查找。您還需要它的一個反轉:

$invert = array(
    'men' => 'man', 
    'octopi' => 'octopus', 
    'octopuses' => 'octopus', 
    'oxen' => 'ox', 
); 
+0

不幸的是,一些單數形式具有相同的複數形式。主要是希臘語和拉丁語貸款詞 – user2180613

+0

這會給你帶來什麼問題? –

+0

是的,因爲鍵必須是唯一的。 – user2180613

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); 
0

輸出:

output 來源:

<!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搜索框,類似於谷歌的預測搜索,但不會顯示可能的結果,因爲搜索字符串是鍵入的,它將縮小搜索範圍,在後臺默默搜索。我有一個腳本可以做到這一點,如果這聽起來可行,可以將它挖掘出來。基本上,不是每個關鍵字都搜索整個字典(我看過一個超過一千二百萬字的字典!),到輸入關鍵字,發送和處理關鍵字時,可能會有更少的循環次數。硬件也值得思考 - 服務器的硬盤,處理器和內存速度將佔據大部分等式。我也聽說C++更適合字典搜索,對於PHP開發人員來說不會太陌生。

+0

$ values可能是一組值(儘管在這種情況下可能不一定)。無論如何...我已經在我的原始方法中完成了這一點。我希望有一些不涉及循環的東西,因爲否則就不會有明顯的速度提升,我將不得不堅持已有的東西。而且,由於一些英文單有多個複數而有些複數有多個英文單(-on(希臘)-um(拉丁語)經常-a複數形式),這將不利於翻轉我目前的陣列。 – user2180613

+0

請參閱編輯 – verbumSapienti