2015-05-17 4 views
0

У меня есть карта, организованная следующим образом. Ключ простой термин позволяет сказать целое число, но значение является сложным набором {BB, CC, DD}. Каков наилучший способ найти минимальный CC на карте? До сих пор у меня есть следующиеНайти минимальное значение на карте

-module(test). 
-author("andre"). 

%% API 
-export([init/0]). 

init() -> 
    TheMap = build(maps:new(), 20), 
    io:format("Map: ~p~n", [TheMap]), 
    AKey = hd(maps:keys(TheMap)), 
    AValue = maps:get(AKey, TheMap), 
    maps:fold(fun my_min/3, {AKey, AValue}, TheMap). 

build(MyMap, Count) when Count == 0 -> 
    MyMap; 
build(MyMap, Count) -> 
    NewMap = maps:put(Count, {random:uniform(100), random:uniform(100), random:uniform(100)}, MyMap), 
    build(NewMap, Count - 1). 

my_min(Key, {A,B,C}, {MinKey, {AA,BB,CC}}) -> 
    if B < BB -> {Key, {A,B,C}}; 
    B >= BB -> {MinKey, {AA,BB,CC}} 
    end. 

Моя карта мала, так что я не слишком беспокоится об использовании AKEY и Avalue найти начальные значения для складки, но мне было интересно, если есть лучший способ, или другая структура данных.

- Спасибо.

ответ

3

То, что у вас есть, близко к хорошему решению, но его можно улучшить. Нет необходимости выкапывать первый ключ и значение, чтобы использовать начальное значение для складки, поскольку вместо этого вы можете просто передать искусственное значение и сделать с ним функцию фолда. Кроме того, вы можете улучшить использование сопоставления шаблонов в головах функций. Наконец, используйте start вместо init, поскольку это облегчает вызов при вызове erl из командной строки.

Вот улучшенная версия:

-module(test). 
-author("andre"). 

%% API 
-export([start/0]). 

start() -> 
    TheMap = build(maps:new(), 20), 
    io:format("Map: ~p~n", [TheMap]), 
    maps:fold(fun my_min/3, {undefined, undefined}, TheMap). 

build(MyMap, 0) -> 
    MyMap; 
build(MyMap, Count) -> 
    NewMap = maps:put(Count, {random:uniform(100), random:uniform(100), random:uniform(100)}, MyMap), 
    build(NewMap, Count - 1). 

my_min(Key, Value, {undefined, undefined}) -> 
    {Key, Value}; 
my_min(Key, {_,B,_}=Value, {_, {_,BB,_}}) when B < BB -> 
    {Key, Value}; 
my_min(_Key, _Value, Acc) -> 
    Acc. 

my_min/3 раз функция имеет три положения. Первый соответствует специальному стартовому значению {undefined, undefined} и возвращает его как новое значение аккумулятора, которое {Key, Value} было передано. Преимущество этого заключается не только в том, что вы избегаете специальной обработки перед запуском складки, но также и в том случае, если карта пуста, в результате вы получите специальное значение {undefined, undefined}, и вы сможете обработать его соответствующим образом. Второе предложение использует охрану для проверки того, является ли значение B значения меньше значения BB в аккумуляторе складок, а если оно есть, верните {Key, Value} в качестве нового значения аккумулятора. Заключительное предложение просто возвращает существующее значение аккумулятора, так как это предложение вызывается только для значений, больших или равных значению в существующем аккумуляторе.

Вы также можете изучить простой список кортежей key/value, поскольку для небольшого количества элементов он может превосходить карту. Если в ваших измерениях указывается, что вы должны использовать список, для него тоже будет работать аналогичная складка.

0
-module(test). 
-author("andre"). 

%% API 
-export([init/0]). 

init() -> 
    TheMap = build(maps:new(), 24), 
    io:format("Map: ~p~n", [TheMap]), 
    List = maps:to_list(TheMap), 
    io:format("List: ~p~n", [List]), 

    Fun = fun({_, {_, V1, _}} = Element, {_, {_, V2, _}}) when V1 < V2 -> 
     Element; 
     (_, Res) -> 
     Res 
    end, 

    Res = lists:foldl(Fun, hd(List), tl(List)), 
    io:format("Res: ~p~n", [Res]). 


build(MyMap, Count) when Count == 0 -> 
    MyMap; 
build(MyMap, Count) -> 
    NewMap = maps:put(Count, {random:uniform(100), random:uniform(100), random:uniform(100)}, MyMap), 
    build(NewMap, Count - 1). 

Вы можете использовать maps:to_list/1 преобразовать карту в список, то вы можете использовать lists:foldl/3 для расчета Minimun значения.