2016-08-22 54 views
2

假設我想做的事是這樣的:什麼是Erlang的流操作方法?

dict 
    .values() 
    .map(fun scrub/1) 
    .flatMap(fun split/1) 
    .groupBy(fun keyFun/1, fun count/1) 
    .to_dict() 

什麼是最優雅的方式在二郎山實現這一目標?

+0

奇怪的是,這是一個構造,我很少需要在我的真實代碼中。我可能會在dict上做一次地圖操作。 – rvirding

回答

3

沒有直接簡單的方法做到這一點。我看到的所有嘗試看起來都比簡單的作文更差。如果你將看Erlang的大部分開源項目,你會發現他們使用通用組合。重新使用你的例子:

to_dict(
groupBy(fun keyFun/1, fun count/1, 
flatMap(fun split/1, 
map(fun scrub/1, 
values(dict))))). 
+0

謝謝。雖然這可惜了:( – BasilTomato

2

這不是一個在Erlang中很自然的構造。如果你有一對夫婦的功能,定期組成是我想要的使用:

lists:flatten(lists:map(fun (A) -> 
          do_stuff(A) 
         end, 
         generate_list())). 

對於較長的一系列操作,中介變量:

Dict = #{hello => world, ...}, 
Values = maps:values(Dict), 
ScrubbedValues = lists:map(fun scrub/1, Values), 
SplitValues = lists:flatten(lists:map(fun split/1, ScrubbedValues)), 
GroupedValues = basil_lists:group_by(fun keyFun/1, fun count/1, SplitValues), 
Dict2 = maps:from_list(GroupedValues). 

這就是它想看看,如果你想讓所有這些行動集中在一起。

不過,我倒是更可能寫這個以不同的方式:

-spec remap_values(map()) -> map(). 
remap_values(Map) -> 
    map_values(maps:values(Map)). 

-spec map_values(list()) -> map(). 
map_values(Values) -> 
    map_values(Values, [], []). 

-spec map_values(list(), list(), list()) -> map(). 
map_values([], OutList, OutGroup) -> 
    %% Base case: transform into a map 
    Grouped = lists:zip(OutGroup, OutList), 
    lists:foldl(fun ({Group, Element}, Acc = #{Group := Existing}) -> 
         Acc#{Group => [Element | Existing]}; 
        ({Group, Element}, Acc) -> 
         Acc#{Group => [Element]} 
       end, 
       #{}, 
       Grouped; 
map_values([First|Rest], OutList, OutGroup) -> 
    %% Recursive case: categorize process the first element and categorize the result 
    Processed = split(scrub(First)), 
    Categories = lists:map(fun categorize/1, Processed), 
    map_values(Rest, OutList ++ Processed, OutGroup ++ Categories). 

實際的正確執行取決於代碼是如何將要運行很多 - 我在這裏寫的很簡單,但可能無法在大量數據上表現良好。如果你真的想要處理無盡的數據流,你需要自己編寫(儘管你可能會發現Gen Server是一個非常有用的框架)。