0

I'm trying to write a map phase for riak in erlang and I've hit a problem. I need to concatenate a description and a code, which are separate items and combine them in the form "code-description", which then needs to be given a value of 1 so "code-description"=1 to allow me to count the same occurrences in my reduce phase (The descriptions are from a static pool, not free text). The dash is also important. Using proplists I can navigate to the values I want and using {struct, values} = ...etc I get something along the lines:

[{"desc":"Stuff Needs Doing","code":"SND"},{"desc":"Done","code":"DNE"}]

When I write the following snippet I get just the desc returning for each kv in my filtered list:

Desc = proplists:get_value(<<"desc">>, Data),
[Desc].

Seeing as how they are both character data I thought that [DescVar ++ CodeVar]. would work but when I ran it against my cluster I actually got an error message and it complains about the ++. + doesn't work either so how do I do what I'm after in erlang?

Nickel
  • 533
  • 1
  • 7
  • 20
  • i wish you could just put what you want your final result to look like from the input you have above – Muzaaya Joshua Dec 12 '12 at 08:08
  • The output I want is [{'SND-Stuff Needs Doing':1, 'DNE-Done':1}]. Sorry about that! I'm not sure if that is valid Erlang you see but I'm trying to write an Erlang equivalent of a js mapreduce query. – Nickel Dec 12 '12 at 09:01

2 Answers2

1

I don't think that your input example is valid in Erlang.

Nevertheless, as an example, if your input would be like this:

[{"desc","A","code","B"}, {"desc","A","code","B"}, {"desc","C","code","B"}]

Then this does want you want:

test() ->
    do([{"desc","Stuff Needs Doing","code","SND"},{"desc","Done","code","DNE"},{"desc","Done","code","DNE"}]).

do(L) -> 
    L2 = lists:map(fun({_,D,_,C}) -> C++"-"++D end, L),
    count(L2,[]).

count([], Acc) -> Acc;
count([H|T], Acc) -> 
    case lists:keytake(H,1,Acc) of
        false -> count(T, [{H,1} | Acc]);
        {value, {H,N}, Acc2} -> count(T, [{H,N+1} | Acc2])
    end.

Output:

1> test:test().
[{"DNE-Done",2},{"SND-Stuff Needs Doing",1}]
2> 
ricardobcl
  • 11
  • 2
1

I haven't played with Riak, but I am assuming you are working with typical erlang decoded json (in [{struct,Values}] format).

[{"desc":"Stuff Needs Doing","code":"SND"},{"desc":"Done","code":"DNE"}]

The above json string would decode to erlang as:

[{struct,[{<<"desc">>,<<"Stuff Needs Doing">>},
      {<<"code">>,<<"SND">>}]},
{struct,[{<<"desc">>,<<"Done">>},{<<"code">>,<<"DNE">>}]}]

Then this List comprehension would give you the results you are looking for (and maintain the correct result format):

[{struct,[{<<X/binary,"-",Y/binary>>,1}]}||{struct,[{<<"desc">>,Y},{<<"code">>,X}]}<-Data].

With "Data" being the erlang decoded JSON.

This produces:

[{struct,[{<<"SND-Stuff Needs Doing">>,1}]},{struct,[{<<"DNE-Done">>,1}]}]

Which encodes to a JSON string as :

[{"SND-Stuff Needs Doing":1},{"DNE-Done":1}]

daedae
  • 26
  • 3