左外连接与Elixir的理解

时间:2015-10-19 01:13:10

标签: elixir

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

我知道python支持它,我已经看过herehere,我想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: []}
]

1 个答案:

答案 0 :(得分:2)

您的第一个示例无法在外部使用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