2016-02-01 29 views
4

我通過elixir使用ets作爲一個簡單的內存中持久層來存儲和檢索密鑰,還偶爾使用foldl來減少許多具有不同值的重複密鑰。我正在使用包選項。如何在不掃描整個表的情況下檢索ets密鑰列表?

是否有一個簡單的O(1)方法可以檢索當前鍵的列表,而無需執行更多涉及的表遍歷或匹配或foldl?

歡迎Erlang或Elixir語法響應。

:ets.new(:cache, [:bag, :named_table, :protected]) 

我有一個原子鍵靜態地圖索引我用來幫助插入的整數。但並不是所有的按鍵均採用..

chunk_key_map = %{2 => :chunk_key_2, ..... 28 => :chunk_key_28} 

如果沒有快速的方法,我知道我可以做一個ETS:查找嘗試對我的每一個靜態原子鍵值和測試= []和產生我自己的列表,但想看看ets是否支持這種功能。

感謝

回答

1

所以我沒有找到ETS技術,而是實現了密鑰列表檢索在固定時間代碼仙丹作爲我的鍵映射是靜態的。

list = Enum.reduce(2..28, [], fn head, acc -> 
      case :ets.lookup(:cache, Map.get(chunk_key_map, head)) do 
       [] -> acc 
       _ -> [acc, head] 
      end 
     end) 

    List.flatten(list) 

更新:根據答覆,我把Hamidreza的ets 遍歷邏輯和使用Stream.resource/3裹成一個藥劑Stream

defp get_ets_keys_lazy(table_name) when is_atom(table_name) do 
    eot = :"$end_of_table" 

    Stream.resource(
     fn -> [] end, 

     fn acc -> 
      case acc do 
       [] -> 
        case :ets.first(table_name) do 
         ^eot -> {:halt, acc} 
         first_key -> {[first_key], first_key}      
        end 

       acc -> 
        case :ets.next(table_name, acc) do 
         ^eot -> {:halt, acc} 
         next_key -> {[next_key], next_key} 
        end 
      end 
     end, 

     fn _acc -> :ok end 
    ) 
end 

然後,我通過管道

get_ets_keys_lazy(table_name) 
    |> Stream.map(lambda1) 
    |> Stream.each(lambda2) 
    |> Stream.run 
+1

這段代碼的問題是,你最終複製所有元素ETS表進入你的過程。請記住,ETS表保持在所有過程的「外部」,因此對ETS表的所有訪問都是通過複製進行的。 'match','match_object'和'select'的一個主要原因是它允許你更加具體地描述哪些元素被複制,可以在元素數據仍然「在表格中」的情況下完成測試。 – rvirding

+0

謝謝羅伯特。我假設你只是指ets.lookup代碼段。不是ets.first,下面的代碼片段也是如此?這非常有幫助。那麼什麼是關鍵檢索的適當的匹配或選擇條款? – bibekp

+0

是的,使用first/next意味着您將訪問每個元素,但它的確意味着您可能只能複製密鑰。 – rvirding

2

跑流爲獲得在ets鍵的列表不接觸它們的值可以使用的ets:first/1ets:next/2功能的組合是這樣的:

-export([keys/1]). 

keys(TableName) -> 
    FirstKey = ets:first(TableName), 
     keys(TableName, FirstKey, [FirstKey]). 

keys(_TableName, '$end_of_table', ['$end_of_table'|Acc]) -> 
    Acc; 
keys(TableName, CurrentKey, Acc) -> 
    NextKey = ets:next(TableName, CurrentKey), 
    keys(TableName, NextKey, [NextKey|Acc]). 

導出的API是keys/1。它獲取表名,獲取它的第一個鍵,啓動一個累加器作爲狀態,並在內部調用keys/2,它獲取其他鍵並以遞歸方式累加它們。

請注意,bag表類型沒有訂單,所以如果您的表類型是bag,則不會訂購返回值keys/1

+0

謝謝Hamidreza – bibekp

+0

由於行李箱允許有重複的鑰匙但具有不同的值,這將返回所有重複的鑰匙嗎? – bibekp

+0

我確認它確實只返回唯一密鑰 – bibekp

5

謝謝,這讓我在正確的軌道:)

同樣的事情,但通過前面的鍵蓄電池上:

def key_stream(table_name) do 
    Stream.resource(
    fn -> :ets.first(table_name) end, 
    fn :"$end_of_table" -> {:halt, nil} 
     previous_key -> {[previous_key], :ets.next(table_name, previous_key)} end, 
    fn _ -> :ok end) 
end 
相關問題