30

I want to be able to extract the Nth item of a tuple in a pipeline, without using with or otherwise breaking up the pipeline. Enum.at would work perfectly except for the fact that a tuple is not an enum.

Here's a motivating example:

colors = %{red: 1, green: 2, blue: 3}
data = [:red, :red, :blue]
data 
|> Enum.map(&Map.fetch(colors, &1))
|> Enum.unzip

This returns {[:ok, :ok, :ok], [1, 1, 3]} and let's say I just want to extract [1, 1, 3]

(For this specific case I could use fetch! but for my actual code that doesn't exist.)

I could add on

|> Tuple.to_list
|> Enum.at(1)

Is there a better way of doing this that doesn't require creating a temporary list out of each tuple?

AnilRedshift
  • 7,937
  • 7
  • 35
  • 59

2 Answers2

71

Use Kernel.elem/2:

iex(1)> {[:ok, :ok, :ok], [1, 1, 3]} |> elem(1)
[1, 1, 3]
Dogbert
  • 212,659
  • 41
  • 396
  • 397
2

Pattern Match can help

{ _status, required_value } = 
  data 
    |> Enum.map(&Map.fetch(colors, &1))
    |> Enum.unzip

You can ignore the _status.

Dinesh Balasubramanian
  • 20,532
  • 7
  • 64
  • 57
  • 1
    I should clarify, the `extract` step is in the middle of the pipeline. Using pattern matching (also my preferred way), ends up requiring intermediate variables and multiple pipes :( – AnilRedshift May 24 '18 at 16:35