Julia中的函数链

时间:2019-05-14 19:46:24

标签: julia

是否可以将多个函数调用作为链写?

sum(
  map(parseIgFloat, 
    map((row) -> row.PL_Amount, 
      filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", 
        collect(ts)
      )
    )
  )
)

将其变成类似:

ts 
  |> collect
  |> filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In")
  |> map((row) -> row.PL_Amount)
  |> map(parseIgFloat)
  |> sum

3 个答案:

答案 0 :(得分:3)

搜索后,这似乎是最好的选择

ts |> 
  collect |> 
  (list -> filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", list)) |>
  (list -> map((row) -> row.PL_Amount, list)) |>
  (list -> map(parseIgFloat, list)) |>
  sum

或带有宏的Pipe

@pipe ts |> 
  collect |> 
  filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", _) |>
  map((row) -> row.PL_Amount, _) |>
  map(parseIgFloat, _) |>
  sum

答案 1 :(得分:2)

通常来说,您要问的是困难的,因为无论您想出什么结构,都必须保证传递的参数顺序是函数期望的顺序,因此没有足够的通用方法允许您无需定义明确的类型和操作即可完成此操作。

但是,相对于mapfilter(特别是 ),创建这些功能的“咖喱”版本并对其应用链接很简单。例如

# Create curried versions of map and filter for use in 'chaining'
import Base.map;    function    map(f); return L ->    map(f,L); end;
import Base.filter; function filter(f); return L -> filter(f,L); end;


f  = x -> x ^ 2;
ts = range(1, stop=10);

( ts
  |>  collect          
  |>  map(f)             # square the collection
  |>  filter(iseven)     # keep only even results
  |>  sum              
)

输出:

220


PS:链接主要是为了简化可读性,如上所述,当您具有一系列连续的简单直观的命令时,链接最有用。如果您要在“链”中使用复杂的表达式,例如提议的解决方案中的表达式,那么我认为这真的不值得。要么将复杂的表达式包装到适当命名的函数中,使它们的链看起来像普通的英语,要么首先避免链接,然后依赖使用临时变量的明确步骤。

PS2:还请注意,|>运算符是广播的有效目标,就像任何功能一样。因此,上面的|> map(f)也可以更简单地写为.|> f

答案 2 :(得分:1)

我可能会这样写:

sum(row -> parseIgFloat(row.PL_Amount),
    filter((row) -> !ismissing(row.Summary) && row.Summary == "Cash In", 
            ts)
    )

如果出现下划线(https://github.com/JuliaLang/julia/pull/24990),您可以像这样简化它:

sum(parseIgFloat(_.PL_Amount)), 
    filter(!ismissing(_.Summary) && _.Summary == "Cash In",  # actually not sure if this line would work
           ts)
    )

那时,链接可能也变得更加方便。

顺便说一句:除非确实需要,否则不要使用collect