Make me more functional. What follows is a hypothetical inspired by actual code.
Lets say I have a list of states: ["bar,", "bar,", "bar,", "baz,", "baz,", "foo,", "foo,", "foo,", "foo"]
that I want to transform into a list of two-element tuples, where the second element is a counter that resets to one each time the state changes. That is, I want this:
[
{"bar", 1},
{"bar", 2},
{"bar", 3},
{"baz", 1},
{"baz", 2},
{"foo", 1},
{"foo", 2},
{"foo", 3},
{"foo", 4}
]
Here is my solution. While it works, that map I’m using as the accumulator for reduce
seems, I don’t know, a bit heavy handed. I suspect there’s a more functional or idiomatic way of going about this, is there? (Ignore the lack lack of pipes.)
things = ~W(bar bar bar baz baz foo foo foo foo)
indexed_things = Enum.reduce(things, %{previous_thing: nil, counter: 0, acc_things: []}, fn thing, acc ->
counter = if acc.previous_thing != thing, do: 0, else: acc.counter
counter = counter + 1
%{previous_thing: thing, counter: counter, acc_things: [{thing, counter} | acc.acc_things]}
end)
IO.inspect Enum.reverse(indexed_things.acc_things)
Thanks, Pete