njwest

njwest

Still fairly new to Elixir and am coming from OOP, so bear with me here…

I have a list of lists of strings, each with a length of 2, ie:

list = [ ["Tony", "Glove"] , ["Mark", "Shirt"], ["Tony", "Hat"] ]

and I want to combine and dedup the lists that have the same value in index[0], so the list above would turn into:

convert_list(list) = [ ["Tony", "Glove", "Hat"], ["Mark", "Shirt"] ]

My first attempt was turning each list into a MapSet, then using:
if MapSet.member do _nothing else MapSet.union(Enum.at(list, x),Enum.at(list,y)

within a recursive for x <- 0..Enum.count(list) function, but I am pretty much in over my head on this one.

Any help/guidance would be greatly appreciated!

Showing Posts 1 to 7

kokolegorille

kokolegorille

Whenever I need to check for key unicity, I would use a map. I would also use Enum.reduce… with some translation due to atom key. The last command line transform the map back to a list.

iex> list 
|> Enum.reduce(%{}, fn [k, v], acc -> Map.update(acc, String.to_atom(k), [v], fn y -> [v | y] end) end) 
|> Enum.map(fn {k, v} -> [to_string(k) | v] end)
[["Mark", "Shirt"], ["Tony", "Hat", "Glove"]]

You might need to reverse some order, as I always add to the head of a list [h | t]

kokolegorille

kokolegorille

In fact, I don’t even need to transform the keys…

iex> list 
|> Enum.reduce(%{}, fn [k, v], acc -> Map.update(acc, k, [v], fn y -> [v | y] end) end) 
|> Enum.map(fn {k, v} -> [k | v] end)
pma

pma

To guarantee list values are deduped one option is to use a MapSet as collector, or just add Enum.uniq/1 to previous solution.

list
|> Enum.reduce(%{}, fn [k, v], m -> Map.update(m, k, MapSet.new([v]), &MapSet.put(&1, v)) end)
|> Enum.map(fn {k, v} -> [k | Enum.to_list(v)] end)
kokolegorille

kokolegorille

That is true, your solution is nicer with the use of MapSet :slight_smile:

njwest

njwest OP

Fascinating, thank you both for the help! I am starting to wrap my head around accumulators and Enum.reduce now.

One more layer of complexity: what if there is another list of items, where it is possible for items to belong to items that belong to a person, ie:

list2 = [ ["Tony", "Glove"] , ["Mark", "Shirt"], ["Tony", "Wallet"], ["Wallet","Money" ] ]

How would you pipe in another Enum.reduce/another function to get:

convert_list2(list2) = [ ["Tony", "Glove", "Wallet","Money" ], ["Mark", "Shirt"] ]

Or would this just require a different initial Enum.reduce?

kokolegorille

kokolegorille

That is more complex.

A hint would be to get all root keys, by filtering the keys that does not exists in the list of values.

values = list2 |> Enum.map(& List.last(&1))
root_keys = list2 |> Enum.map(& List.first(&1)) |> Enum.filter(& !Enum.member?(values, &1)) |> Enum.uniq

Then, in some loop, treat the root keys as is, and the others as belonging to a sub tree.

Not to mention edge case like this…

[“Mark”, “Wallet”], [“Tony”, “Wallet”]

OvermindDL1

OvermindDL1

What immediately jumps to my mind is:

╰─➤  iex
Erlang/OTP 20 [erts-9.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.6.0-dev) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> list = [ ["Tony", "Glove"] , ["Mark", "Shirt"], ["Tony", "Hat"] ]                     
[["Tony", "Glove"], ["Mark", "Shirt"], ["Tony", "Hat"]]
iex(2)> list |> Enum.group_by(&hd/1) |> Enum.map(&Enum.uniq(List.flatten(elem(&1, 1))))
[["Mark", "Shirt"], ["Tony", "Glove", "Hat"]] 
iex(3)> 

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews