I have a list of structs and want to update the first record to include similar ids as children. Not sure if there is a good way to do it other than iterating over it.
I was trying out group_by to create a list where structs with identical keys are together but i have multiple ids so if id key is empty it should use uid instead. since it uses either uid or id as its key, there might be duplicates?
If so you’ll need to be more explicit about the transformation rules, and it might help to have some context. E.g. why does one record have a uid and not id? Why is there a parent at the end but no children following it etc?
@demem123: I’m not 100% sure about your rules, but let me know if this example fits them:
defmodule Example do
def collect_children(list), do: Enum.reduce(list, [], &do_collect_children/2)
defp do_collect_children(element, acc) do
cond do
element.test == "parent" -> [element | acc]
element.id == "" ->
update_children(acc, element, :uid)
true ->
update_children(acc, element, :id)
end
end
defp update_children(acc, element, key) do
index = Enum.find_index(acc, &(&1[key] == element[key]))
update_in(
acc,
[Access.at(index), :children],
&do_update_children(&1, element)
)
end
defp do_update_children(nil, element), do: [element]
defp do_update_children(list, element), do: [element | list]
end
list = [
%{"id": 1, "test": "parent"},
%{"id": 1, "test": "child1"},
%{"id": 1, "test": "child2"},
%{"uid": 1, "test": "parent", id: ""}
]
IO.inspect Example.collect_children(list)
Note: Here parents and children are reversed. You can reverse them again using &Enum.reverse/1 or by replacing tail calls like: [element | list] to: list ++ [element].
hey! Thanks! yep trying to transform the data. I was using ecto to get the data from the table and the table has multiple foreign keys so there are times that other ids doesnt have any values in it. =)