IOEnthusiast
IOEnthusiast

Reputation: 107

Pipe operator after conditional in elixir

  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

Answers (4)

Aleksei Matiushkin
Aleksei Matiushkin

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

Everett
Everett

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

David Maze
David Maze

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

sabiwara
sabiwara

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

Related Questions