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
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
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
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
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
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










