Reputation: 107
def smallestNumber(list) do
[head | tail] = Enum.sort(list)
case head === 0 do
true ->
[tempHead | tempTail] = tail
String.to_integer(Enum.join([tempHead | [head | tempTail]],""))
false -> String.to_integer(Enum.join([head | tail],""))
end
end
How could I avoid this repetition? I would like to do something like this
def smallestNumber(list) do
[head | tail] = Enum.sort(list)
case head === 0 do
true ->
[tempHead | tempTail] = tail
[tempHead | [head | tempTail]]
false -> [head | tail]
end
|> String.to_integer(Enum.join,"")
end
Upvotes: 0
Views: 253
Reputation: 121010
While all three answers here so far are correct, I see the XY Problem here: [0, 0, 1, 2]
should be most likely sorted as [1, 0, 0, 2]
which is not the case for any of the above.
In such a case, one should better use recursion.
def sort(list, acc \\ [])
def sort([], acc), do: acc # exhausted
def sort([0 | tail], acc), do: sort(tail, [0 | acc])
def sort([any | tail], acc), do: [any | acc] ++ tail
now do whatever you want with the result.
Another way round would be to use Enum.split_while/2
Enum.split_while([0, 0, 1, 2], &match?(0, &1))
and then remap the result.
Answering the exact question stated, simply use
…
|> case do
end
|> Enum.join("") # `""` is redundant fwiw
|> String.to_integer()
Upvotes: 2
Reputation: 9628
If you want a pipeline, I posit the following:
def shuffle_number(list) do
list
|> Enum.sort()
|> case do
[0 | [second_smallest | tail]] -> [second_smallest | [0 | tail]]
passthru -> passthru
end
|> Enum.join("")
|> String.to_integer()
end
IO.puts(shuffle_number([3, 4, 2, 1])) # 1234
IO.puts(shuffle_number([0, 4, 2, 1])) # 1024
This is a bit unusual in the pattern matching, but you can see a bit into how linked lists work: the first element is the head and everything else is the tail. I've never done this kind of nested pattern-matching on lists before, but it is a valid way to de-structure (or to re-structure).
I think that's the behavior you described, but it would be helpful if you provided inputs and desired outputs.
Upvotes: 1
Reputation: 159830
If I'm reading the case
statement correctly, then if the (sorted) list begins with zero, swap it with the second element; otherwise use the (sorted) list as-is. You can break that out into a helper function
def not_zero_first([0 | [first | list]]), do: [first | [0 | list]]
def not_zero_first(list), do: list
With this helper function in hand, you can have a pipeline without any conditionals or logic in it
def smallest_number(list) do
list
|> Enum.sort()
|> not_zero_first()
|> Enum.join("")
|> String.to_integer()
end
Upvotes: 1
Reputation: 3214
The typical way to achieve this would be to pipe into the two functions successively:
case head do
0 ->
[temp_head | temp_tail] = tail
[temp_head, head | temp_tail]
_ ->
[head | tail]
end
|> Enum.join("")
|> String.to_integer()
If you really want to pipe into a more complex function, you could consider then/2
but it wouldn't be idiomatic for this case:
|> then(&String.to_integer(Enum.join(&1, "")))
Upvotes: 1