【问题标题】:Enum.reduce to put strings into the right listEnum.reduce 将字符串放入正确的列表中
【发布时间】:2018-10-15 02:08:57
【问题描述】:

我有这个函数可以将字符串拆分成多个部分,我需要将这些部分放入params 映射中的正确列表中。

parts = String.split(term_string, " ")

params = %{
  search_terms: [],
  wildcard_terms: [],
  minus_terms: [],
  room_terms: [],
  messages_to_terms: [],
  messages_from_terms: [],
  date_before_terms: [],
  date_after_terms: [],
  date_on_terms: [],
  date_during_terms: []
}

Enum.reduce(parts, params, fn p ->
  cond do
    String.ends_with?(p, "*") ->
      params[:wildcard_terms] = [p | params[:wildcard_terms]]

    true ->
      params[:search_terms] = [p | params[:search_terms]]
  end
end)

我现在收到cannot invoke remote function Access.get/2 inside match 错误,我不知道如何解决这个问题。

有什么建议吗?

【问题讨论】:

  • 这里的根本问题是你没有以一成不变的方式思考。 params[:wildcard_terms] = [p | params[:wildcard_terms]] 没有做你认为的事情。它不会更新与地图params 中的键关联的值,因为您可能习惯于使用其他语言,例如 Ruby/Java/Python。这就是为什么 dogbert 的解决方案提倡使用 Map.update!,它在幕后创建了一个新地图,除了与指定键对应的值之外,其他值都相同。

标签: list dictionary enums elixir reduce


【解决方案1】:

虽然@Dogbert 的解决方案确实非常健壮,但我会稍微重构一下这段代码以使其更简洁:

Enum.reduce(parts, params, fn p ->
  key =
    if String.ends_with?(p, "*") do
      :wildcard_terms
    else
      :search_terms
    end

  Map.update!(params, key, fn ps -> [p | ps] end)
end)

或者,如果您更喜欢更冗长(并且速度较慢 - 请参阅下面有价值的 Dogbert 评论)但易于阅读的方法(基于匹配映射器参数):

parts
|> Enum.map(&String.reverse/1)
|> Enum.reduce(params, fn
     <<"*", _::binary>> = p -> 
       %{params | wildcard_terms: [p | params.wildcard_terms]}
     p ->
       %{params | search_terms: [p | params.search_terms]}
   end)

【讨论】:

  • 第二个会非常慢 - ends_with? 是 O(1) 而String.reverse 将复制整个二进制文件 (O(n))。
  • @Dogbert 是的,确实,谢谢。我已添加通知;我不确定当需要reverse 时这是否更易读,但我想总体上宣讲/演示模式匹配方法。
【解决方案2】:

您需要在缩减函数中返回一个包含更新列表的新地图。一种方法是使用Map.update!

Enum.reduce(parts, params, fn p ->
  cond do
    String.ends_with?(p, "*") ->
      Map.update!(params, :wildcard_terms, fn ps -> [p | ps] end)

    true ->
      Map.update!(params, :search_terms, fn ps -> [p | ps] end)
  end
end)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多