shahryarjb

shahryarjb

Hi friends, I have a nested list that is unstructured, and I really know how much it has nested list or map in itself.

I just need to search and get all :tag key in this list and check the selected name by my user exists there or it is unique.

For example:

[
  %{
    children: [
      %{
        children: [],
        id: "fcfb1066-6e16-4a84-81e0-7746f12b7e76",
        tag: "test1",
        type: "section"
      },
      %{
        id: "035ca737-2cc2-488b-83f5-fe7cc2becc5e",
        parent_id: "a9963499-f6a4-4a32-bafa-aa22a9b059bc",
      },
      %{
        children: [
          %{
            other: [
              %{
                id: "035ca737-2cc2-488b-83f5-fe7cc2becc5e",
                parent_id: "a9963499-f6a4-4a32-bafa-aa22a9b059bc",
              },
            ],
            tag: "test4",
          },
        ],
        id: "8a9f0126-33a0-4c03-8c4a-5507f0562c8a",
        index: 2,
        parent: "layout",
        parent_id: "a9963499-f6a4-4a32-bafa-aa22a9b059bc",
        tag: "test2",
        type: "section"
      }
    ],
    parent: "dragLocation",
    parent_id: "dragLocation",
    tag: "test3",
  }
]

This list has no a structure that helps me to use Enum.

So I try to use macro, but based on my little knowledge I could not to find all :tag, see this code please

defmacro get_tags(data, selected_name) do
  quote do
    data = unquote(data)
    data_string = inspect(data, charlists: :as_strings)
    ast = Code.string_to_quoted(data_string)
    
    ....
  end
end

the ast = Code.string_to_quoted(data_string) passes me a nested list again, and I don’t know how to create a pattern to get tag, so after that I use to List.flatten ast but I got this error:
** (FunctionClauseError) no function clause matching in :lists.flatten/1

because It has maps in its list

Please help me to learn more about macro and search like this in a list, Thank you in advance.

Showing Posts 1 to 10

tcoopman

tcoopman

I don’t understand why you want to use a macro to solve this.

What I’d suggest is a recursive search.

shahryarjb

shahryarjb OP

Hi @tcoopman, Thank you for response

The first reason is to learn more about macros and second one is I try recursive function to find all tag in a list, but it needs so much condition to find it is map? Or list of it is so enumerable it and find map or list again so get tag etc.

Because the list I get from a user is not a structured list, and maybe it has multiple layers in only one parameter

do you have any suggestion about it, like sample code or sth?

tcoopman

tcoopman

This is something that should work:

  def find([], tags), do: tags

  def find([hd | tl], tags) do
    tag = Map.get(hd, :tag)
    tags = if tag, do: [tag | tags], else: tags

    child = Map.get(hd, :children)
    tags = if child, do: find(child, tags), else: tags

    find(tl, tags)
  end
shahryarjb

shahryarjb OP

Yes, I wrote something before like this, but as I said it has more complicity for me because maybe we have no children sometimes we have a single map into another map that has tag or childrent name is something like other

  def get_tags(data) do
    get_tags_helper(data, %{})
    |> Map.values()
    |> Enum.uniq()
  end

  defp get_tags_helper(data, tags) do
    case data do
      [] -> tags
      [head | tail] ->
        case head[:tag] do
          nil -> get_tags_helper(head[:children] ++ tail, tags)
          tag ->
            new_tags = Map.update(tags, tag, 1, &(&1 + 1))
            get_tags_helper(head[:children] ++ tail, new_tags)
        end
      _ -> tags
    end
  end

But thank you, the recursive is my selected option, at least. If you have an idea with macro, please let me know, I really want to improve my level in meta programming. :rose:

tcoopman

tcoopman

I’m not very fluent with macros either. Having said that, I really don’t see how macros are going to help you with the problem at hand.
Macros are not something you should just reach to, they are powerful but also add complexity. So only use them when necessary.

Back to your problem:
If there are no children, or no tags, my solution handles that.
If the children is not named children, how do you know it’s something you should decent into?
What is the actual problem you’re trying to solve?

shahryarjb

shahryarjb OP

Yes, I pointed out exactly this problem at the beginning of the project, but now this decision has been made at higher levels than me
Unfortunately, we have a list that different people in different organizations add a series of parameters to this list based on their taste.
All I have to do is find all the tags and check if the new name I want to insert has already been inserted.

It should be noted, sometimes some added list has no tag that should be avoided or skipped. This is true for children.
I tried to do it with the search string and check it is included whether there is, for example, tag: name or not, but sometimes I need to take this tag and make some changes on it.

That’s why I tried to move this whole list of strings to the macro and check each and every line of it.

tcoopman

tcoopman

Macros are not magic. They won’t lower the complexity of the problem.
What I would do is write test cases for the different kinds of inputs you need to handle and then implement code for them.

LostKobrakai

LostKobrakai

Macros are for turning one piece of “pseudo” code into another piece of code. That’s useful if you know some information at compile time, which you can then turn into more/different code. You don’t seem to have any information at runtime, which would help you solve the problem at hand.

hst337

hst337

Use Pathex

import Pathex.Combinator
import Pathex.Lenses
import Pathex

tag_lens =
  combine(fn rec ->
    path(:tag, :map) ||| (star() ~> rec)
  end)

Pathex.view(nested_stuff, tag_lens ~> matching("test2"))
hst337

hst337

For the future questions, if you want to traverse nested structures, just use lenses. This is a very powerful tool which solves the problems in a few lines

It is like writing a filesystem path, but for elixir structures

— All posts loaded —

Where Next? Top

Trending in Questions Top

Blokh
Hey guys, I’ve got a huge CSV ( around 10 GB ) that needs to be processed hourly Do you guys have any suggestions what is the best prac...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
psy-q
I’m trying to set up Emacs with elixir-ls via lsp-mode and credo via Flycheck. This should mostly be preconfigured as Flycheck picks up c...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews