otuv

otuv

Grouping and extract values from list of maps

Hi,
I have a list of maps such as:

[%{x: a, y: 1}, %{x: a, y: 1}, %{x: b, y: 0}, %{x: b, y: 1}]

From this I would like to find out how many 1s a and b have respectively

ie. resulting in something like:

[a: 2, b:1]

(or something to that effect)

I have accomplished this using rather brute force and un-elixirish ways and do feel there should be a rather elegant solution but it has eluded me so far and any help is appreciated.

Marked As Solved

factoryd

factoryd

One, pretty straight-forward, way to accomplish what you’re after is to think in the steps of what you want.

  1. You want to group your list into keys and the values of each unique key
  2. You want to count the unique values (in your example, you want to count the 1s)

So you have something like this:

[%{x: :a, y: 1}, %{x: :a, y: 1}, %{x: :b, y: 0}, %{x: :b, y: 1}]
    |> Enum.group_by(fn %{x: x} -> x end, fn %{y: y} -> y end)
    |> IO.inspect(label: "grouped")
    |> Enum.reduce([], fn {key, values}, acc ->
      acc ++ [key, Enum.count(values, fn x -> x == 1 end)]
    end)

Now you may think this is very specific to finding the count of 1s. And you’re right.

To make it more general is just as easy.
Just think of the steps you need to take to get what you want.

It’s exactly as above with an extra step of finding the values of n. …and use some functions to be kind to others. :stuck_out_tongue:

defmodule Playground do
  def hello do
    [%{x: :a, y: 1}, %{x: :a, y: 1}, %{x: :b, y: 0}, %{x: :b, y: 1}]
    |> count_values()
    |> count_value(1)
    |> IO.inspect(label: "count of 1s by key")
  end

  defp count_values(list) do
    list
    |> Enum.group_by(fn %{x: x} -> x end, fn %{y: y} -> y end)
    |> IO.inspect(label: "values grouped by key")
    |> Enum.reduce([], fn {key, values}, acc ->
      counts =
        Enum.reduce(values, %{}, fn value, acc ->
          Map.update(acc, value, 1, &(&1 + 1))
        end)

      acc ++ [{key, counts}]
    end)
    |> IO.inspect(label: "values counted")
  end

  defp count_value(list, n) do
    Enum.reduce(list, [], fn {key, values}, acc ->
      count =
        values
        |> Enum.filter(fn {value, _} -> value == n end)
        |> Enum.map(fn {_, count} -> count end)
        |> IO.inspect(label: "#{key} #{n}s")

      # ensure we use zero if we have no results in `count`
      count =
        case count do
          [n] -> n
          _ -> 0
        end

      acc ++ [{key, count}]
    end)
  end
end

Now that you have your answers, clean it up however you feel is necessary.

Cheers!

Also Liked

shanesveller

shanesveller

What did you try already? What felt less-than-ideal to you about it?

I’d probably just start with an Enum.reduce and go from there, because this is pretty similar conceptually to the “count the occurrence of a letter or word in a string” problem that frequently appears in coding koans/challenges/exercises.

dimitarvp

dimitarvp

Are a and b variables? Your given code snippet is not valid Elixir otherwise. They could be atoms (:a and :b) or strings ("a" and "b").

otuv

otuv

Now I feel rather embarrassed. I simply missed that there was a count/2. In hindsight this is rather obvious in language like this.

Where Next?

Popular in Questions Top

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
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
chewm
Hi guys, nice to meet you to the whole forum, I’m new here, I’m trying to configure visual studio code for elixir, right now the intellis...
New
sabri
Can someone explain the settings of pool_size of Ecto in config file? and what is the recommend size? Thanks
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
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
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New

Other popular topics Top

lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
273 38985 115
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

We're in Beta

About us Mission Statement