michaelb

michaelb

Filter list of maps

Hello!
I’m trying to filter list of maps to remove items where value of key was declared previously in this list. List that I have:

list = [%{
    "distance" => "4",
    "source" => "source_1",
},
%{
    "distance" => "2",
    "source" => "source_1",
},
%{
    "distance" => "5",
    "source" => "source_2",
},
%{
    "distance" => "1",
    "source" => "source_2",
},
%{
    "distance" => "2",
    "source" => "source_2",
}]

List what I want to get:

[%{
    "distance" => "4",
    "source" => "source_1",
},
%{
    "distance" => "5",
    "source" => "source_2",
}]

I tried next code:

sources = []
list
|> Enum.filter(fn p ->
    if p["source"] in sources do
        false
    else
        sources ++ p["source"]
        true
    end
end) |> IO.inspect

But looks like list “sources” not accessed from Enum.filter. Probably there exist more correct solution for this?

Marked As Solved

amnu3387

amnu3387

There’s Enum.uniq_by/2 that you can use, as in Enum.uniq_by(list, fn(%{"source" => s}) -> s end)

The reason your filter doesn’t work is because you’re building the list as you enumerate the elements and you can’t mutate the variable sources. You can achieve what you want with a reduction, where you keep track of them as you exemplified:

{_, new_list} = Enum.reduce(list, {[], []}, fn(%{"source" => s} = el, {sources, acc}) ->
                               if(s in sources, do: {sources, acc}, else: {[s | sources], [el | acc]}) 
                end)

final = :lists.reverse(new_list)

https://hexdocs.pm/elixir/Enum.html#uniq_by/2

Also Liked

vlarok

vlarok

  def single(list) do
   Enum.uniq_by(list, &(%{"source" => &1.source}))
  end
kokolegorille

kokolegorille

Here is my one line ugly try :slight_smile:

iex> list |> Enum.reduce(%{}, fn %{"source" => s} = x, acc -> Map.put_new(acc, s, x) end) |> Enum.map(fn {_k, v} -> v end)        
[
  %{"distance" => "4", "source" => "source_1"},
  %{"distance" => "5", "source" => "source_2"}
]

I use Map.put_new to ensure only first source is persisted

OvermindDL1

OvermindDL1

For note, your sources ++ p["source"] expression is evaluated here but the result is thrown away since it’s not being returned.

And it looks like you aren’t just wanting a unique one based on the name, but also the one with the highest value in each set, thus I’d probably do either this:

Enum.group_by(list, & &1["source"]) |> Enum.map(fn {_, v} -> Enum.max_by(v, & &1["distance"]) end)

Or this:

Enum.sort_by(list, & {&1["source"], &1["distance"]}, &>/2) |> Enum.dedup_by(& &1["source"])

Or any of a variety of other ways. :slight_smile:

Where Next?

Popular in Questions Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 45766 226
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 42633 214
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New

We're in Beta

About us Mission Statement