docjazither

docjazither

Delete the 1st pair in a map

Hi OGs,
How can I delete the 1st pair in a map ?
Thank you

First Post!

msimonborg

msimonborg

AFAIK maps are unordered, so there is no “first”. You could enumerate over it, collecting all but the first in the enumeration, but I think it would be an arbitrary selection so I’m not sure there’s much difference between that and Map.delete(map, random_key)

Most Liked

sodapopcan

sodapopcan

OP doesn’t seem to care that they are out of order but I’m dying to know the use-case :joy:

adamu

adamu

Please post your code showing how your map is constructed. As @msimonborg said, there is no such concept of the “first” item in a map.

jhogberg

jhogberg

Erlang Core Team

If you don’t specifically need a map, consider using :gb_trees instead. Its take_smallest/1 and take_largest/1 operations are bound to be quicker than converting to list, sorting, deleting the first entry, and then creating a map again.

Last Post!

docjazither

docjazither

Yep
The task is to find duplicate entries and delete everything and spare the most optimal one

defmodule Mix.Tasks.App.CleanUpDuplicateAccounts do
  use Mix.Task

  import Ecto.Query, only: [where: 3, from: 2]

  alias App.Data.{....
  }

  require Logger

  def run(_args) do
    Logger.info("Starting task to clean up duplicate accounts...")

    {:ok, _} = Application.ensure_all_started(:data)

    query =
      from(u in User,
        where:
          fragment(
            "exists (
                select 1
                from users inner
                where inner.id != ?
                and lower(inner.email) = lower(?)
              )",
            u.id,
            u.email
          ),
        order_by: u.email
      )

    query
    |> Repo.all()
    |> Enum.group_by(&String.downcase(&1.email))
    |> Enum.each(fn {_k, duplicates} ->
      comparing_statuses(duplicates)
    end)
  end

  defp get_tasks_for_users(id) do
        # Logic return tasks
  end

  defp check_and_remove_account(user) do
    if !user.is_email_verified ||
         is_nil(user.encrypted_password) do
      tasks = get_tasks_for_user(user.id)

      case tasks do
        [] ->
          Logger.info("Deleting user: id #{user.id} with email #{user.email}")
          Users.delete(user)

        _ ->
          Logger.info("Unable to delete - user: id #{user.id} has active tasks")
      end
    end
  end

  defp mass_deletion_check(duplicates) do
    are_all_duplicates_not_verified =
      Enum.all?(duplicates, &(!&1.is_email_verified || is_nil(&1.encrypted_password)))

    if are_all_duplicates_not_verified do
      [_ | duplicates_to_delete] = duplicates

      Enum.each(
        duplicates_to_delete,
        fn index ->
          check_and_remove_account(index)
        end
      )
    else
      Enum.each(duplicates, fn index ->
        if !index.is_email_verified or is_nil(index.encrypted_password) do
          check_and_remove_account(index)
        else
          Logger.info(
            "Not deleting - user: id #{index.id} has email is verified or password is set"
          )
        end
      end)
    end
  end

  defp get_handle_for_user(id) do
        # logic to return handles
  end

  # If handles are the same then start mass_deletion_check for the duplicates
  # If handles are different then delete email from accounts except one
  defp handle_or_email_deletion_check(duplicates) do
    duplicates_with_handle =
      duplicates
      |> Enum.reduce([], fn user, acc ->
        acc ++ [Map.put(user, :handle, get_handle_for_user(user.id))]
      end)

    handle_group = Enum.group_by(duplicates_with_handle, & &1.handle)

    if Enum.count(handle_group) < 2 do
      mass_deletion_check(duplicates)
    else
      [_ | handle_group_to_delete_email] = Enum.to_list(handle_group)

      Enum.each(handle_group_to_delete_email, fn {_k, duplicates} ->
        remove_email_except_one(duplicates)
      end)
    end
  end

  defp remove_email_except_one(duplicates) do
    Enum.each(duplicates, fn user ->
      Users.update(user, %{email: nil})
    end)
  end

  defp count_with_status(duplicates, status) when not is_list(status) do
    count_with_status(duplicates, [status])
  end

  defp count_with_status(duplicates, status) do
    Enum.count(
      duplicates,
      &(&1.user_status_id in UserStatuses.get_id_by_code(status))
    )
  end

  defp accumulating(duplicates, status) do
    duplicates
    |> Enum.reduce([], fn user, acc ->
      if user.user_status_id in UserStatuses.get_id_by_code(status) do
        acc ++ [user]
      else
        check_and_remove_account(user)
        acc
      end
    end)
  end

  defp accumulating_accounts_with_required_status(duplicates, status)
       when status == "approval_requested" do
    duplicates_account_with_approval_requested = accumulating(duplicates, [status])

    delete_all_and_update_first_one(duplicates_account_with_approval_requested)
  end

  defp accumulating_accounts_with_required_status(duplicates, status) when not is_list(status) do
    duplicates_to_delete = accumulating(duplicates, [status])

    mass_deletion_check(duplicates_to_delete)
  end

  defp accumulating_accounts_with_required_status(duplicates, status) do
    duplicates_to_delete = accumulating(duplicates, status)

    mass_deletion_check(duplicates_to_delete)
  end

  defp iterate_and_remove(duplicates, status)
       when not is_list(status) do
    iterate_and_remove(duplicates, [status])
  end

  defp iterate_and_remove(duplicates, status) do
    Enum.each(duplicates, fn user ->
      if user.user_status_id not in UserStatuses.get_id_by_code(status) do
        check_and_remove_account(user)
      end
    end)
  end

  defp iterate_and_update(duplicates, status) do
    Enum.each(duplicates, fn user ->
      if user.user_status_id ==
           UserStatuses.get_id_by_code(status) do
        Users.update(user, %{email: nil})
      end
    end)
  end

  defp iterate_and_update(duplicates, status_one, status_two) do
    Enum.each(duplicates, fn user ->
      if user.user_status_id !==
           UserStatuses.get_id_by_code(status_one) do
        check_and_remove_account(user)
      else
        Users.update(user, %{
          user_status_id: UserStatuses.get_id_by_code(status_two)
        })
      end
    end)
  end

  defp deleting_with_approached_and_approved_case(duplicates) do
    duplicates_approved_and_approached =
      Enum.reduce(duplicates, [], fn user, acc ->
        if user.user_status_id !== UserStatuses.get_id_by_code("approved") and
             user.user_status_id !==
               UserStatuses.get_id_by_code("approached") do
          check_and_remove_account(user)
          acc
        else
          acc ++ [user]
        end
      end)

    handle_from_approved =
      get_handle_for_user(Enum.at(duplicates_approved_and_approached, 0).id)

    handle_from_approached =
      get_handle_for_user(Enum.at(duplicates_approved_and_approached, 1).id)

    case {handle_from_approved, handle_from_approached} do
      {handle_from_approved, handle_from_approached}
      when handle_from_approved == handle_from_approached and not is_nil(handle_from_approved) and
             not is_nil(handle_from_approached) ->
        iterate_and_remove(
          duplicates_approved_and_approached,
          "approached"
        )

      _ ->
        iterate_and_update(
          duplicates_approved_and_approached,
          "approached"
        )
    end
  end

  defp delete_all_and_update_first_one(duplicates) do
    [user_to_update | duplicates_to_delete] = duplicates
    Enum.each(duplicates_to_delete, fn user -> check_and_remove_account(user) end)

    Users.update(user_to_update, %{
      user_status_id: UserStatuses.get_id_by_code("approved")
    })
  end

  defp count_duplicates_statuses(duplicates) do
    approved_count = count_with_status(duplicates, "approved")

    invalid_count =
      count_with_status(duplicates, [
        "invalid",
        "under_investigation",
        "suspended"
      ])

    approached_count = count_with_status(duplicates, "approached")

    rejected_count = count_with_status(duplicates, "rejected")

    external_count = count_with_status(duplicates, "external")

    approval_requested_count = count_with_status(duplicates, "approval_requested")

    {approved_count, invalid_count, approached_count, rejected_count, external_count,
     approval_requested_count}
  end

  defp comparing_statuses(duplicates) do
    statuses = count_duplicates_statuses(duplicates)
    handle_statuses(statuses, duplicates)
  end

  defp handle_statuses({1, _, 0, _, _, _}, duplicates) do
    iterate_and_remove(duplicates, "approved")
  end

  defp handle_statuses({1, _, 1, _, _, _}, duplicates) do
    deleting_with_approached_and_approved_case(duplicates)
  end

  defp handle_statuses(
         {approved_count, _, 0, _, _, _},
         duplicates
       )
       when approved_count >= 2 do
    accumulating_accounts_with_required_status(duplicates, "approved")
  end

  defp handle_statuses({0, 1, _, _, _, _}, duplicates) do
    iterate_and_remove(duplicates, [
      "invalid",
      "under_investigation",
      "suspended"
    ])
  end

  defp handle_statuses({0, invalid_count, _, _, _, _}, duplicates) when invalid_count >= 2 do
    accumulating_accounts_with_required_status(duplicates, [
      "invalid",
      "under_investigation",
      "suspended"
    ])
  end

  defp handle_statuses({0, 0, 1, _, _, 0}, duplicates) do
    iterate_and_remove(duplicates, "approached")
  end

  defp handle_statuses({0, 0, 1, _, _, 1}, duplicates) do
    iterate_and_update(
      duplicates,
      "approval_requested",
      "approved"
    )
  end

  defp handle_statuses({0, 0, approached_count, _, _, approval_requested_count}, duplicates)
       when approached_count >= 2 and approval_requested_count >= 2 do
    accumulating_accounts_with_required_status(duplicates, "approval_requested")
  end

  defp handle_statuses({0, 0, approached_count, _, _, 0}, duplicates)
       when approached_count >= 2 do
    iterate_and_remove(duplicates, "approached")

    handle_or_email_deletion_check(duplicates)
  end

  defp handle_statuses({0, 0, 0, 1, _, _}, duplicates) do
    iterate_and_remove(duplicates, "rejected")
  end

  defp handle_statuses({0, 0, 0, rejected_count, _, _}, duplicates) when rejected_count >= 2 do
    accumulating_accounts_with_required_status(duplicates, "rejected")
  end

  defp handle_statuses({0, 0, 0, 0, 1, _}, duplicates) do
    iterate_and_remove(duplicates, "external")
  end

  defp handle_statuses({0, 0, 0, 0, external_count, _}, duplicates) when external_count >= 2 do
    accumulating_accounts_with_required_status(duplicates, "external")
  end

  defp handle_statuses({0, 0, 0, 0, 0, approval_requested_count}, duplicates)
       when approval_requested_count >= 2 do
    mass_deletion_check(duplicates)
  end
end

Where Next?

Popular in Questions Top

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
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
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
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New

We're in Beta

About us Mission Statement