如何从 Elixir 中的结构/映射/嵌套结构/映射中删除键

问题描述 投票:0回答:1

你好,我有这个结构

  request = %Model{
    id: 4_269_615,
    site_id: 3,
    user_id: 183_317,
    program_id: 174,
    type: %ProgramType{
      value: :CASHBACK_PROGRAM,
      __unknown_fields__: []
    },
    type_data: %ProgressProgramUser{
      id: 1_336_676,
      valid_stake: nil,
      level: nil,
      theo_ggr: nil,
      __unknown_fields__: []
    },
    start_at: ~U[2024-09-05 13:27:20.391727Z],
    end_at: nil,
    inserted_at: ~U[2024-09-05 13:27:24.152602Z],
    program_name: "test cb program 20 min GOLD NFT",
    __unknown_fields__: []
  }

我正在尝试从结构以及嵌套结构中删除

__unknown_fields__: []

我正在使用的代码正在运行

  def drop_unknown_fields(struct) when is_struct(struct) do
    struct
    |> Map.from_struct()
    |> drop_unknown_fields()
  end

  def drop_unknown_fields(%{} = map) when is_map(map) do
    map
    |> Enum.reduce(%{}, fn {key, value}, acc ->
      updated_value =
        case date?(value) do
          true -> value
          false -> drop_unknown_fields(value)
        end

      Map.put(acc, key, updated_value)
    end)
    |> Map.delete(:__unknown_fields__)
  end

  def drop_unknown_fields(value), do: value

  def date?(%DateTime{}), do: true
  def date?(%Date{}), do: true
  def date?(%NaiveDateTime{}), do: true
  def date?(_), do: false

但我认为这不是正确的做法。检查日期的原因是:当我尝试执行嵌套结构时,datatime 也是一个结构,并且它被解析为映射,这不是必需的。所以你能指导我一些最佳的方法来清理这个结构并删除

:__unknown_fields__
谢谢你

更新:我用下面的代码重构了它,但仍在寻找建议。

  def drop_unknown_fields(struct) when is_struct(struct) do
    struct
    |> Map.from_struct()
    |> only_consider_unknown_fields(struct)
    |> drop_unknown_fields()
  end

  def drop_unknown_fields(%{} = map) when is_map(map) do
    map
    |> Enum.reduce(%{}, fn {key, value}, acc ->
      updated_value =  drop_unknown_fields(value)

      Map.put(acc, key, updated_value)
    end)
    |> Map.delete(:__unknown_fields__)
  end

  def drop_unknown_fields({:consider, map}), do: drop_unknown_fields(map)

  def drop_unknown_fields({:ignore, struct}), do: struct

  def drop_unknown_fields(value), do: value

  defp only_consider_unknown_fields(map, struct) do
    case Map.has_key?(map, :__unknown_fields__) do
      true -> {:consider, map}

      false -> {:ignore, struct}
    end
  end
elixir
1个回答
0
投票

这是一个我认为按照您想要的方式工作的实现。

  1. 具有该特定键的结构体将转换为映射,该特定键将被删除,并且它们的值将被递归处理。

  2. 其他结构保持原样。

  3. 然后处理非结构映射的值并将其转换回映射。

  4. 任何其他值保持原样。

  def drop_unknown_fields(%_{__unknown_fields__: _} = struct) do
    for {k, v} <- Map.from_struct(struct), k != :__unknown_fields__, into: %{} do
      {k, drop_unknown_fields(v)}
    end
  end

  def drop_unknown_fields(%_{} = struct), do: struct

  def drop_unknown_fields(%{} = map) do
    for {k, v} <- map, into: %{}, do: {k, drop_unknown_fields(v)}
  end

  def drop_unknown_fields(value), do: value

输出:

%{
  id: 4269615,
  type: %{value: :CASHBACK_PROGRAM},
  site_id: 3,
  user_id: 183317,
  program_id: 174,
  type_data: %{id: 1336676, level: nil, valid_stake: nil, theo_ggr: nil},
  start_at: ~U[2024-09-05 13:27:20.391727Z],
  end_at: nil,
  inserted_at: ~U[2024-09-05 13:27:24.152602Z],
  program_name: "test cb program 20 min GOLD NFT"
}

完整代码:

defmodule Model do
  defstruct [
    :id,
    :site_id,
    :user_id,
    :program_id,
    :type,
    :type_data,
    :start_at,
    :end_at,
    :inserted_at,
    :program_name,
    :__unknown_fields__
  ]
end

defmodule ProgramType do
  defstruct [
    :value,
    :__unknown_fields__
  ]
end

defmodule ProgressProgramUser do
  defstruct [
    :id,
    :valid_stake,
    :level,
    :theo_ggr,
    :__unknown_fields__
  ]
end

defmodule Main do
  def main do
    request = %Model{
      id: 4_269_615,
      site_id: 3,
      user_id: 183_317,
      program_id: 174,
      type: %ProgramType{
        value: :CASHBACK_PROGRAM,
        __unknown_fields__: []
      },
      type_data: %ProgressProgramUser{
        id: 1_336_676,
        valid_stake: nil,
        level: nil,
        theo_ggr: nil,
        __unknown_fields__: []
      },
      start_at: ~U[2024-09-05 13:27:20.391727Z],
      end_at: nil,
      inserted_at: ~U[2024-09-05 13:27:24.152602Z],
      program_name: "test cb program 20 min GOLD NFT",
      __unknown_fields__: []
    }

    request |> drop_unknown_fields() |> IO.inspect()
  end

  def drop_unknown_fields(%_{__unknown_fields__: _} = struct) do
    for {k, v} <- Map.from_struct(struct), k != :__unknown_fields__, into: %{} do
      {k, drop_unknown_fields(v)}
    end
  end

  def drop_unknown_fields(%_{} = struct), do: struct

  def drop_unknown_fields(%{} = map) do
    for {k, v} <- map, into: %{}, do: {k, drop_unknown_fields(v)}
  end

  def drop_unknown_fields(value), do: value
end

Main.main()
© www.soinside.com 2019 - 2024. All rights reserved.