Reputation: 1598
I am trying to parse unix-style flags from an args
list, i.e.:
args = ["hello", "-f", "val", "-u", "valtwo"]
# Desired outcome: [{"-f", "val"}, {"-u", "valtwo"}]
I've managed to extract the flags with the following regex:
args
|> Enum.filter(fn arg -> Regex.match?(~r/^-{1,2}\w+/, arg) end)
# ["-f", "-u"]
However, in order to get the values that correspond to these keys, I need to get the value of args at the next index.
I've considered transforming the array using Enum.chunk_every(2)
(discarding the first element, "hello"
), but that's not sufficiently flexible, since that will break on the following:
["hello", "-f", "val", "secondvalforf", "-u", "valtwo"]
# Achieved outcome: [{"-f", "val"}, {"secondvalforf", "-u"}, {"valtwo"}]
Any ideas are greatly appreciated.
Upvotes: 0
Views: 89
Reputation: 121000
Enum.reduce/3
is your friend here.
args = ~w|hello -f val foo -u valtwo|
#⇒ ["hello", "-f", "val", "foo", "-u", "valtwo"]
Enum.reduce(args, [], fn
<<?-, _>> = key, args -> [{key, []} | args]
_, [] -> [] # skip plain arguments
arg, [{key, last} | rest] -> [{key, last ++ [arg]} | rest]
end)
#⇒ [{"-u", ["valtwo"]}, {"-f", ["val", "foo"]}]
Call Enum.reverse/1
on the result to preserve the order of keys (reduce
prepends new elements to the accumulator to avoid creating many subsequent linked lists down the road.)
Upvotes: 2