Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Power Query 系列 (06) - M 语言结构化数据类型

Power Query 系列 (06) - M 语言结构化数据类型

原创
作者头像
StoneWM
修改于 2019-12-13 10:41:46
修改于 2019-12-13 10:41:46
1.9K0
举报
文章被收录于专栏:Stone的专栏Stone的专栏

本篇介绍 Power Query M 语言的三种结构化类型(或称为容器类型):List、Record 和 Table,它们是 Power Query 数据处理的核心。了解本篇三种容器类型后,应该能大体看懂查询编辑器和高级编辑器中的代码逻辑。

List

List 中文翻译为列表,跟 Python 语言的 list 很类似,由一序列有顺序的元素构成,这些元素可以是不同的数据类型。M 语言的 List 由一对大括号来,每个元素之间用逗号分隔。

A List is a zero-based ordered sequence of values enclosed in curly brace characters { }. The curly brace characters { } are also used to retrieve an item from a List by index position.

定义一个由 1 到 5 的整数组成的 List:

代码语言:txt
AI代码解释
复制
{1, 2, 3, 4, 5}  // 由 1 到 5 的整数构成的 List

我们在查询编辑器中来看一下。创建一个空白查询(请参考上一篇如何创建空查询),然后在公式栏中输入 {1, 2, 3, 4, 5},点击"对号"确认。

确认后,查询编辑器的显示区显示了列表的值,左边是索引:

切换到功能区【主页】,点击【关闭并上载】,看看 Excel Sheet 中列表的显示效果。

M 语言提供 .. 符号表示表示连续的元素,比如从 1 到 100:

代码语言:txt
AI代码解释
复制
{1..100}

连续符号不仅仅被用作数字,也可以用于单个字符,比如我们想列出所有的字母,包括大写字母和小写字母:

代码语言:txt
AI代码解释
复制
{"a".."z", "A".."Z"}

Power Query (PQ) 为什么能够理解从 a 到 z 呢,背后的原理就是这些字母的 Unicode 的编码,中文的 Unicode 编码大致范围在 19968-40891 之间,所以,我们也可以构造出所有中文(包括汉字和字符)字的列表:

代码语言:txt
AI代码解释
复制
List.Transform({19968..40891}, Character.FromNumber)

List 的元素是有顺序的,使用从 0 开始的索引获取 List 中的元素:

代码语言:txt
AI代码解释
复制
numbers = {1..10}
first = numbers{0}  // first element
last = numbers{9}  // last element

如果有更复杂条件的存取,需要用到标准库的函数,比如:

代码语言:txt
AI代码解释
复制
- List.First
- List.Last
- List.FirstN
- List.LastN

假设有一个从 1 到 100 的列表,要取出列表最后的 5 个元素:

代码语言:txt
AI代码解释
复制
let
     source = {1..100},
     lastFive =  List.LastN(source, 5)
in
     lastFive

Record (记录)

Record 类似于 Python 中的 dict,用于表达有键值对 (key-value pair) 的数据。Record 用一对中括号 [] 来包含,不同键值对用逗号分隔,键 (key)没有引号:

A Record is a set of fields. A field is a name/value pair where the name is a text value that is unique within the field’s record. let Product = [Product="TV", Price=1800] in Product

将列表上载到 Excel Sheet 中的效果:

Record 是键值对,使用 key 来读取 Record 中的值,比如:

代码语言:txt
AI代码解释
复制
let
     source = [Product="TV", Price=1800],
     product = source[Product]
in
     product

通常情况下,我们的数据都是由行和列构成的表格形式,对于这种格式,可以用 List 和 Record 组合来表示,每一行是一个 Record,多个 Record 组成一个 List:

代码语言:txt
AI代码解释
复制
let
     products = {
          [product="TV", price=1800],
          [product="Computer", price=6800]
     }
in 
     products

在查询编辑器中的显示如下:

如果我们读取 Computer 的价格:products{1}[price]

代码语言:txt
AI代码解释
复制
let
     products = {
          [product="TV", price=1800],
          [product="Computer", price=6800]
     },
     computerPrice = products{1}[price]
in 
     computerPrice

Table (查询表)

Table 是由行和列构成的数据集合,一般 Table 都是从外部数据源导入到 PQ 中,但也可以用 M 脚本手工创建。

A Table is a set of values organized into named columns and rows. The column type can be implicit or explicit.

手工创建 table 的基本方法是按行构建:

代码语言:txt
AI代码解释
复制
products = #table(
     // columns
     {
          "Product", "Price"
     },
     // lines
     {
          {"TV", 1800},
          {"Computer", 5600}
     }

查询编辑器界面的显示:

上面创建查询表的方法,没有指定数据类型,用下面的语法创建 Table 的同时,指定 Column 的数据类型:

代码语言:txt
AI代码解释
复制
let 
	products = #table( type table 
	     // columns
	     [
	          Product = text, Priece = number
	     ],
	     // lines
	     {
	          {"TV", 1800},
	          {"Computer", 5600}
	     }
	)
in 
     products

标准库中提供了 Table.FromXXX 函数来创建 Table,可以根据需要来学习,这里提供其中的两种:

Table.FromRecords()

语法

代码语言:txt
AI代码解释
复制
Table.FromRecords(records as list, 
				optional columns as any, 
				optional missingField as nullable number) as table

将 records 或者 record 构成的 list 转换成 table,可以理解为按行构建 table。举一个例子:

代码语言:txt
AI代码解释
复制
let
    scores = {
        [Name="张三", Subject="语文", Score= 98],
        [Name="李四", Subject="语文", Score= 90],
        [Name="张三", Subject="数学", Score= 100],
        [Name="李四", Subject="数学", Score= 87],
        [Name="张三", Subject="英语", Score= 60],
        [Name="李四", Subject="英语", Score= 72]
    },
    source = Table.FromRecords(scores)
in
    source

Table.FromColumns()

按列构建一个 table,需要一个 list 作为参数语法如下:

代码语言:txt
AI代码解释
复制
Table.FromColumns(lists as list, optional columns as any) as table

上面的示例数据,使用 Table.FromColumns() 函数构建:

代码语言:txt
AI代码解释
复制
let 

     source = Table.FromColumns(
         {
            {"张三","李四", "张三","李四","张三","李四"},
            {"语文","语文","数学","数学", "英语","英语"},
            {98,90,100,87,60, 72}
         },
         {"Name", "Subject", "Score"}
     )
in 
    source

获取行的值

Table 每一行是一个 record 类型的数据,所有行可以看成由 record 构成的 list:

代码语言:txt
AI代码解释
复制
products = {
          [product="TV", price=1800],
          [product="Computer", price=6800]
     },

Table 每一列是 list 类型的数据,所有列可以看成由 list 构成的 record

代码语言:txt
AI代码解释
复制
products = [
     Product={"TV", "Computer"},
     Price={1800, 5600}
]

上面两句如何看待行和列的方式是理解读取 table 中行、列和单元格值的基础。怎么读取行的数据呢?比如我们要读取第一行所有列,可以这样:

代码语言:txt
AI代码解释
复制
navigation = products{0}  // 第一行所有列

获取列的值

比如上面的表,想获取 Product 整列的数据

代码语言:txt
AI代码解释
复制
prodName = products[Product]

获取单元格的值

在上面方法,能获取到行或列之后,获取单元格的值就比较简单了:

代码语言:txt
AI代码解释
复制
productName = products{0}[Product]   // 先读取行 (record),再根据 record 的 key 读取
productName = products[Product]{0}  // 先读取列 (list),再根据 list 的索引读取

还有一种更直观的方式,这种方式比较直观,尽量应该采用这种方法:

代码语言:txt
AI代码解释
复制
productName = products{[Product="TV"]}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
剑指Offer全解
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
racaljk
2019/03/29
1K0
剑指offer-刷题总结
分析:由于每一行都有递增的特性,我们可以采用类似二分搜索的方法。将数组分成行列来进行搜索。
小二三不乌
2018/08/07
2K0
《剑指offer》全部题目-含Java实现
陆续刷了好久,算是刷完了《剑指offer》,以下全部AC代码,不一定性能最优,如有错误或更好解答,请留言区指出,大家共同交流,谢谢~ 1.二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 public class Solution { public boolean Find(int target, int [][] array) { if(arra
10JQKA
2018/05/09
3.1K0
《剑指offer》全部题目-含Java实现
剑指offer题目汇总_朝花夕拾题目及答案填空题
>> : 右移运算符,num >> 1,相当于num除以2
全栈程序员站长
2022/11/09
9830
剑指offer(16-30题) 精解
比如两个链表你可以用一个list1作为主链表返回。返回另一个list2进行遍历比较插入到主链表适当位置中。有兴趣可以试一试。 当然你还可以直接建立一个新链表头节点value。list1和list2同时遍历,取小的节点添加到value为头节点的链表中。同时小的那个链表向下进行下一轮比较。直到list1和list2都为null为止。
bigsai
2020/02/19
4560
剑指offer(31-40)题解
又因为他要求我们是从小到大排序然后输出,所以我们就需要对满足这种格式的数据进行排序,但是这里的难点就是我们如何才能实现排序的 思路是既然通用公式已经确定,我们也不能看出其实数据从后部分开始一定都是前某一项的倍数,而且这个倍数一定是由2,3,5交叉组合而成,所以我们只需要通过判断,将次结算之后最小的那个数添加到我们的数组中即可,但是也不要顽疾通过光标来计数,2,3,5这三个质因子的位置。
萌萌哒的瓤瓤
2020/08/26
3770
剑指offer(31-40)题解
剑指Offer-1
---- 做了又忘,忘了又做,怎么刷都是学不会啊啊啊 1 从每行每列都是递增的二维数组中找是否存在某数 public class Solution { public boolean Find(int target, int[][] array) { int rows = array.length; int cols = array[0].length; int i = rows - 1; int
晚上没宵夜
2020/12/08
3590
剑指offer(31-40题)题解
思路: 最笨的方法(可过)。使用字符串,将从1道n的字符串拼凑成新的字符串,然后遍历查找1就可以了。至于数学方法的话当初想了一会感觉考虑点挺多,后面还会再想想。
bigsai
2020/02/19
3880
剑指offer(25-30)题解
剑指offer(25-30)题解 25题解--复杂链表的复制 26题解--二叉搜索树与双向链表 27题解--字符串的排列 28题解--数组中出现次数超过一半的数字 29题解--最小的K个数 30题解--连续子数组的最大和 25题解–复杂链表的复制 题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) 思路解析
萌萌哒的瓤瓤
2020/08/26
3750
剑指offer(25-30)题解
剑指Offer 23-44题(Python版)
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
小一
2019/08/14
6930
python-剑指offer21-40
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
西西嘛呦
2020/08/26
5680
80道高频算法题Python版
掌握这80道题,99%的测试岗位算法考试都能通过。建议收藏后反复练习。本文为Python版本答案,对于Java版本答案,请在电子书《算法挑战》目录中查看。
dongfanger
2023/09/30
8920
80道高频算法题Python版
【面试必备】手撕代码,你怕不怕?
这绝对是属于重点了,不管是考察对于该重要模型的理解还是考察代码能力,这都是一道很好的考题,所以很有必要的,我们先来回顾一下什么是生产者-消费者问题;
我没有三颗心脏
2018/09/14
1.9K0
【面试必备】手撕代码,你怕不怕?
剑指Offer 1-22题(Python版)
题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
小一
2019/08/14
4760
刷题:剑指offer第四期(33-44)
33.把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
前端迷
2020/02/19
4120
剑指offer(47-67题)终极篇
思路: 这题首先要理解题意吧。题目就是给了两个操作,insert和FirstAppearingOnce两个函数,至于一些其他需要你自己实现。你可以选择字符数组、或者String做容器储存。这里我是用StringBuider储存。
bigsai
2020/02/19
5120
剑指offer【50~59】
排序数组,很明显二分查找,找到第一个 >= k 的元素索引以及第一个 > k 的元素索引,两者相减即为答案,即 lowerBound - upperBound。时间复杂度为 O(logn),空间复杂度为 O(1)。
echobingo
2019/12/20
4020
力扣
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100176.html原文链接:
全栈程序员站长
2021/05/21
1.4K0
力扣
算法题目(四)
题目:我们把只包含因子2、3 和5 的数称作丑数(Ugly Number)。求从小到大的顺序的第1500个丑数。
Helloted
2022/06/06
3660
算法题目(四)
牛客网面试高频榜单TOP10总结 Javascript算法学习(一)
TOP1 /*function ListNode(x){ this.val = x; this.next = null; }*/ function ReverseList(pHead) // 本题主要是利用递归的思想,我们首先要判断临界条件 // 然后把这个递归调用的函数当成一个可以实现功能的黑盒 // 只要临界条件设对了,那么递归就能实现我们想要的功能 { // 临界条件 // 首先判断单链表要是为空或者只有一个节点 那么就直接返回 if(!pHead || !
henu_Newxc03
2022/05/05
1810
牛客网面试高频榜单TOP10总结 Javascript算法学习(一)
相关推荐
剑指Offer全解
更多 >
LV.1
这个人很懒,什么都没有留下~
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档