Power Query 经常被描述为无代码或低代码数据处理工具,因为我们无需编写一行代码就可以在 Power Query 中对数据进行转换处理。只需单击鼠标即可选择许多功能,然后它们就会以近乎神奇的方式工作。
在我们点击鼠标的这个过程中,我们会在公式栏中反复看到的一个词是 each。
例如,在下图中,我们对地区列进行了一个筛选,选择地区列的值为东北的行。
each 出现了,这里 each 的作用是什么呢?为什么不直接是 [地区] = "东北" 。
我们来看一下官方文档对 each 的解释。
each 是一个关键字,用于轻松创建简单函数。“each ...”是采用 _ 参数“(_) => ...”的函数签名的语法糖。
语法糖是什么?_ 参数的函数签名是什么?还有,为什么简单地筛选 [地区] = "东北" 不使用 each 就不行呢?
我们以上面的筛选函数 Table.SelectRows() 为例,一起来看一下 each 它到底有什么用。
Table.SelectRows() 语法如下,第一个是表,第二个是函数。
例子如下,第一个是更改的类型表,第二个是 each ([地区] = "东北"),这里提出一个问题,([地区] = "东北") 是函数吗?
Table.SelectRows() 要求第二个参数是函数,而 ([地区] = "东北") 不是函数,是一个判断条件,它返回 True/False 布尔值,所以 each 在这里的作用是将 ([地区] = "东北") 变成一个函数吗?
粗略地说,函数是一段可以重复执行的代码块。
函数通常具有一个或多个输入值(所谓的参数)。此外,函数还具有返回值(结果),一个简单的函数为:
我们在括号中定义函数的参数,上面例子中的 x 和 y。箭头 (=>) 之后是函数体,在函数体中确定返回值。在上面的例子中,返回值是一个数值布尔值。
在 M 中,很多情况下我们只需要处理一个参数。例如,如果我们想比较输入值是否大于 5。
在这些情况下,我们可以用 _ 来代替来代表输入值表示唯一的参数,最终得到以下函数。
这就引出了语法糖,语法糖是在某些情况下对语法的简化。如果我们只处理一个参数,M 的语法允许我们选择不同的简化符号。
这意味着,我们可以简单地省略函数箭头部分(括号及其内容),而直接使用 each 来访问隐式(单一)参数 _。
(输入值) => 输入值 > 5
(_) => _ > 5
each _ > 5
上述表达式都做着完全相同的事情:它们取一个数字,判断它是否大于 5,然后返回 true 或 false。
这有什么好处呢?在更复杂和嵌套的函数中,这种表示法可以显著提高代码的可读性。
Power Query 中的函数不仅可以接收数字或文本(字符串)作为参数。实际上,通过内置的 M 函数 Table.SelectRows(table as table, condition as function),我们可以看到整个表或一个函数都可以作为函数参数。
除了整个表,我们还经常需要处理行,这意味着我们经常需要以行作为参数的函数。
假设表中有一个单价列,因此每行都有一个名为单价的字段,我们希望将其增加 5 并返回结果。
我们如何访问行的字段?通过使用所谓的引用操作符:[ ],或更具体地说:行[列名]。
现在,结合引用操作符,简化程度进一步提高。如果我们有一个参数,即一行,则可以使用引用符号 [] 直接访问此行中的字段。然后该函数如下所示。
each [单价] + 5
Table.SelectRows() 函数需要表作为第一个参数的函数,即应该被筛选的表,然后函数逐行遍历该表。
对于每一行,Table.SelectRows() 执行第二个参数,即 Fuction 函数。该函数将当前行作为参数传递。因此,函数必须接受一行作为参数。最后,我们的函数必须包含一些搜索条件,如果找到则返回 true,否则返回 false。如果返回 false,Table.SelectRows() 将忽略当前行。如果结果为 true,该行将添加到新表中。这样,Table.SelectRows() 在处理所有行后最终返回一个新的筛选表。
因此,最终结果是:
Table.SelectRows(更改的类型, each [地区] = "东北")
Table.SelectRows() 采用步骤更改的类型中的表,并逐行遍历该表。对于每一行,它调用函数 each [地区] = "东北",将当前行作为参数传递,在该行中查找地区字段,并检查该字段中的值是否为东北。如果值是东北,函数将在当前行返回 true ,Table.SelectRows() 会将该行保留在筛选后的表中。如果值不是东北,函数将返回 false ,Table.SelectRows() 则不会在筛选后的表中显示该行。
现在,我们终于知道了 each 和 _ 的含义以及 M 语言中的函数是什么样的!
只有掌握了 each 和 _ 的用法,我们在处理行数据时才会更加的得心应手。这里也问大家一个问题,如果相对一行进行操作应该怎么做呢?比如对一行的列名添加一个前缀,知道的小伙伴可以在留言区留言哦。
点击“阅读原文”获取更多资源