What would be the best way to get adjacent values for given value inside a list. Something like:
list = [7, 3, 8, 1, 5, 9]
val = 1
[head | val | tail] = list
And now in the head I can check the last element (that would be 8), and in the tail I can check the first element (that would be 5). But that doesn’t work Any other “clever” method to get that values?
list = [7, 3, 8, 1, 5, 9]
val = 1
# at 1 because enumerables are 0-based
list |> Enum.split_while(fn elem -> elem != val end) |> elem(1) |> Enum.at(1)
# It's not as fast for previous element, but still easy to get:
list |> Enum.split_while(fn elem -> elem != val end) |> elem(0) |> Enum.at(-1)
list |> Enum.split_while(fn elem -> elem != val end) |> elem(0) |> List.last()
Thank you for all the answers! But I think in the end I will go with:
list = [7, 3, 8, 1, 5, 9]
val = 9
index = Enum.find_index(list, fn e -> e == val end)
case index do
0 ->
{nil, Enum.at(list, index + 1)}
_ ->
{Enum.at(list, index - 1), Enum.at(list, index + 1)}
end
Sorry I misunderstood your request.
The recursive function above finds the right adjacent value.
This one below finds the 2 adjacent:
def adjs([], _), do: []
def adjs([val, right | t], value) when val == value, do: right
def adjs([left, val, right | t], value) when val == value, do: {left, right}
def adjs([_h | t], value) do
adjs(t, value)
end
This seems the best solution here if you count time, but in my case, there is db query anyway, so I don’t care that much. But this is the solution that I will go when I would consider time!
Also, keep in mind to return in the format of {:ok, value}, {:ok, value1, value2}, :error
otherwise if you just get {value1, value2} or [] you will never be sure if you are getting two values, or the one value you got is a two-element tuple.
Here there is no possible error. Max, it returns nil.
Also, the return value spec being either nil, or an integer or a tuple allows, via pattern matching, to distinguish the different cases.
One could do
adjs(list)
|> case do
nil -> :foo
val when is_integer(val) -> :bar
{left, right} -> :baz
end
Well, if the list only contians integers, yes. But it is never mentioned that. It talks about value, so I expect a tuple, nil, or and empty list could be a value as well.