shahryarjb
Need advise to update nested list 3-level
Hello friends, I have a list that I want to update it (3 level nested), and I need your suggestion to create better code
The list
elements = [
%{
children: [
%{
children: [
%{
children: [],
class: ["text-black", "w-full", "p-2"],
id: "c9ea0fff-1ee0-407e-8b2a-64afc954c40b",
index: 0,
parent: "section",
parent_id: "62197198-e3a1-46de-8f18-f2c6843f646f",
type: "text"
},
%{
children: [],
class: ["text-black", "w-full", "p-2"],
id: "b2a6b171-26e1-4e8a-8cd3-c41f388de6e8",
index: 1,
parent: "section",
parent_id: "62197198-e3a1-46de-8f18-f2c6843f646f",
type: "text"
}
],
class: ["flex", "flex-col", "justify-between", "items-stretch",
"min-h-[200px]", "w-full", "border", "border-dashed",
"border-gray-400", "p-1"],
id: "62197198-e3a1-46de-8f18-f2c6843f646f",
index: 0,
parent: "layout",
parent_id: "64a2c3f2-d71f-464a-8318-be072d7b6624",
type: "section"
}
],
class: ["flex", "flex-row", "justify-start", "items-center", "w-full",
"space-x-3", "px-3", "py-10"],
id: "64a2c3f2-d71f-464a-8318-be072d7b6624",
index: 0,
parent: "dragLocation",
parent_id: "dragLocation",
type: "layout"
}
]
for updating and adding tag to the text element I did like this, but it is very dirty I think:
def add_tag(elements, id, parent_id, layout_id, tag, type) when type in @elements do
Enum.map(elements, fn
%{type: "layout", id: ^layout_id, children: children} = selected_layout ->
edited_list =
children
|> Enum.map(fn
%{type: "section", id: ^parent_id, children: children} = selected_section ->
element_edited_list =
Enum.map(children, fn
%{type: ^type, id: ^id} = selected_element ->
Map.merge(selected_element, %{tag: tag})
element ->
element
end)
%{selected_section | children: element_edited_list}
section ->
section
end)
%{selected_layout | children: edited_list}
layout ->
layout
end)
end
MishkaTemplateCreatorWeb.MishkaCoreComponent.add_tag(elements, "c9ea0fff-1ee0-407e-8b2a-64afc954c40b", "62197198-e3a1-46de-8f18-f2c6843f646f", "64a2c3f2-d71f-464a-8318-be072d7b6624", "test1", "text")
By the way, for finding I created this code:
def find_element(elements, id, parent_id, layout_id, type) when type in @elements do
Enum.flat_map(elements, fn
%{type: "layout", id: ^layout_id, children: children} ->
case Enum.find(children, &(&1.id == parent_id)) do
nil ->
[]
%{type: "section", id: ^parent_id, children: children} ->
if is_nil(data = Enum.find(children, &(&1.id == id))), do: [], else: [data]
end
_layout ->
[]
end)
|> List.first()
end
Thank you in advance
Most Liked
jegaxd26
shahryarjb
hst337
Pathex is just like Elixir’s builtin Access, but structure-friendly, user-friendly, more performant and with some other cool features. They both use the same approach called “Functional optics”. Long story short, this approach is about writing fn functions which can set/get/update value in a structure (like getters or setter in OOP languages), and libraries like Pathex or Access are providing interface to create these functions and compose them together.
This approach is really useful and I suggest everyone to learn some optics, because it is universal way to traverse any nested structure. There are XPaths for XML, there are CSS selectors for HTML, there is dot-notation for structures, there is Access for primitive structures, but these approaches are format-specific, which is strange since everything in Elixir is represented as a combination of maps, lists and tuples. So, Pathex just leverages this feature and significantly reduces amount of stuff one must know to traverse nested data in Elixir. Just master Pathex and you can traverse XML, HTML, nested JSON or anything else using one tool.
So, there’s no magic, there are just functions, hehe
Last Post!
Sebb
agree, only that it is most of the time way easier to work in a flat structure. May be a little slower to render, but will not be relevant in this use case.
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
- #forms
- #api
- #metaprogramming
- #hex
- #security









