kodepett

kodepett

Is there a straightforward way of retrieving an element in this list [ {"server", "nginx"}, {"date", "Sat, 13 Nov 2021 18:25:48 GMT"}, {"content-type", "UTF-8"}, {"content-length", "23"}, {"freeflow", "FB"} ]

I’m afraid the ordering might change and hence can’t rely on elem . I’ve perused the doc and can’t find a straightforward of extracting individual fields using the first element(string) in the tuple as the key.

Showing Posts 1 to 10

thiagomajesk

thiagomajesk

If you can’t rely on the order I guess you’d have to use Enum.filter and friends.

PS: You could also transform this list into a map and use that map as a lookup.

mpope

mpope

If the elements are always tuples of two, I think you can use Keyword.get/3. Something like:

req =
  [ 
    {"server", "nginx"},
    {"date", "Sat, 13 Nov 2021 18:25:48 GMT"}, 
    {"content-type", "UTF-8"},
    {"content-length", "23"},
    {"freeflow", "FB"}
  ]
server = Keyword.get(req, "server")
krstfk

krstfk

Not necessarily the most efficient but should work (not tested) :

def get_elem([{key, v}| _tl], str) when key == str do
   {:ok, v}
end
def get_elem([_ | tl ], str), do: get_elem(tl, str)
def get_elem([], _str), do: :error_not_found

It’s also not necessarily the most idiomatic, Enum.find would be better.
Keyword won’t work since the first element of your tuple is a string and not an atom.

josevalim

josevalim

Creator of Elixir

Unfortunately Keyword expects the keys to be atoms. To lookup for any key, use List.keyfind/3 instead, such as:

List.keyfind(list, “server”, 0)

The above will look up on a list of tuples returning the first element where the position 0 of the tuple is the string ”server”.

kodepett

kodepett OP

Awesome, thank you.

krstfk

krstfk

TIL List.keyfind/3 is backed by a BIF. Nice, thanks.

eksperimental

eksperimental

Filter will return all the elements that have “server” as the first element of the tuple.

eksperimental

eksperimental

Just to illustrate another possibility,

You can use Enum.find/3 and Enum.find_value/3

iex> Enum.find_value(list, fn {"server", v} -> v; _ -> nil end)   
"nginx"

Enum.find_value is useful since you already know the key, you are probably interested in the value. Anyway I think it is more performant List.keyfind + pattern matching since it is a built-in internal function.

Another comment is that Elixir v1.13 is introducing List.keyfind!/3 you can read more about it here: List — Elixir v1.13.0-rc.0

krstfk

krstfk

I don’t want to hijack this topic, however the fact that List.keyfind/3 is backed by a bif got me curious.

I suspect, that this is because there’s no way to implement that function with arbitrary length tuples (should I say n-uples ?), and keys at arbitrary position, in pure Erlang, rather than raw speed considerations.

Benchmarking this leads to surprising results, on my machine with otp 24 with jit enabled:

defmodule Experiments do
  def get_elem(str, [{str, el} | _tl]) , do: el
  def get_elem(_str, []), do: :error_not_found
  def get_elem(str, [_ | tl]), do: get_elem(str, tl)

end

with

list = Enum.to_list(1..10_000_000)
tuples = Enum.map(list, fn el -> {"#{el}", "#{el}" } end)

Benchee.run(%{
  "get elem" => fn -> Experiments.get_elem("9999999", tuples) end,
  "keyfind" => fn -> List.keyfind(tuples, "9999999", 0) end,
}
)

gives the following result :

Operating System: macOS
CPU Information: Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz
Number of Available Cores: 8
Available memory: 16 GB
Elixir 1.12.3
Erlang 24.1.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s

Benchmarking get elem...
Benchmarking keyfind...

Name               ips        average  deviation         median         99th %
get elem          7.31      136.76 ms     ±4.42%      134.81 ms      163.94 ms
keyfind           5.63      177.49 ms     ±6.72%      174.30 ms      234.07 ms

Comparison:
get elem          7.31
keyfind           5.63 - 1.30x slower +40.73 ms

That’s not to say one should use a custom function in that situation (as always, with performances, one should consider the input size, strike a balance between readability and gains, and benchmark if needed), it was just interesting.

josevalim

josevalim

Creator of Elixir

You can implement it using regular Elixir:

defmodule Experiments do
  def keyfind([head | tail], val, pos) when elem(head, pos) === val, do: head
  def keyfind([_ | tail], val, pos), do: keyfind(tail, val, pos)
  def keyfind([], _val, _pos), do: nil
end

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
Onor.io
I have what I’ve heard referred to as a “lookup table” in my database. This is a way of assigning codes to common values. One common lo...
New
jaybe78
Hello, I’m developing a online persistent chat system (what’s app) like using elixir/dynamodb/aws for a mobile app(flutter). The diffic...
New
Trolleger
What approach to take when sending live updates to “random” users Hi! I have a question, I have a little chat app, and when I create a DM...
New
matt-savvy
Anyone here using Honeybadger? My Honeybadger account is being overwhelmed with noise from some bots. Seeing a lot of Bandit.HTTPError...
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews