elixir - 左外连接与 Elixir 的理解

我一直在研究我可以用 EnumStreamfor comprehensions 做些什么,我正在努力重现 left outer加入行为。我可以使用 Enum.reduce 实现左外连接函数,但如果有某种方法可以使用 for 实现,我宁愿使用它。

我知道python支持它,我见过它here和 here ,我想 Elixir 的理解是受 python 的启发。我们可以在 Elixir 中实现吗?

假设我有两个来自外部 API 或一些 json/xml 文件的列表:

categories = [%{id: 1, name: "beverages"}, %{id: 2, name: "vegetables"}]
products = [%{name: "ice tea", category: 1}, %{name: "sake", category: 1}]

我想离开外部加入他们以获得类似的东西:

cat_product == [
  %{category: "beverages", product: "ice tea"},
  %{category: "beverages", product: "sake"},
  %{category: "vegetables", product: "(No product)"}
]

还有类似的东西:

cat_products == [
  %{name: "beverages", products: [list of products]}
  %{name: "vegetables", products: []}
]

最佳答案

您的第一个示例不能优雅地在外部使用 for 循环编写,因为左侧列表中的记录可以连接到右侧列表中的多个记录。然而,for 推导式将最多为原始集合中的每个元素生成一个结果。在这种情况下,使用 Enum.flat_map 会更合适:

Enum.flat_map categories, fn(c) ->
  case Enum.filter(products, fn(p) -> p.category == c.id end) do
    [] ->
      [%{name: c.name, product: nil}]
    prods ->
      for p <- prods, do: %{name: c.name, product: p.name}
  end
end

你的第二个例子可以很容易地用 for 理解来实现,因为在原始集合中的每个元素的结果集中总是只有一个元素。过滤不是使用 Enum.filter,而是使用内部 for 理解的第二个参数完成,这使代码更清晰。

for c <- categories do
  prod = for p <- products, p.category == c.id do
    p.name
  end
  %{name: c.name, products: prod}
end

https://stackoverflow.com/questions/33205141/

相关文章:

iis - 如何在没有收到确认消息的情况下退出 IIS Express 工作进程?

laravel - 如何在 Laravel 的容器中重新绑定(bind)?

gstreamer - 使用 Gstreamer 编码/解码 VP8 或 VP9?

maven - 在 Nexus 中部署后,POM.xml 中的变量没有被解析?

c++11 - 将 char16_t 转换为 long/integer,(相当于 atoi/atol

session - 身份验证为匿名的用户已尝试访问拥有的 session

codeigniter - 从数据库下载文件或在 codeigniter 中保存文件夹

html - HTML LocalStorage 中的数据在其他窗口/选项卡中可用所需的时间

angularjs - 如何使用 Firebase 和 AngularJS 创建评论线程?

android - 将抽屉导航添加到现有的 Android 谷歌地图