跳到主要内容

Sheet 二维数组表类

Sheet 是 Alia 的内置二维数组表类,用于处理多个数组之间的映射关系,是类似 Excel 表格的数据结构。支持高效的表格操作、数据查找和表连接功能。

创建 Sheet​

使用表头和数据创建​

const headers = ['id', 'name', 'age', 'city']
const data = [
[1, 'Alice', 25, 'Beijing'],
[2, 'Bob', 30, 'Shanghai'],
[3, 'Charlie', 35, 'Guangzhou']
]
const sheet = new Sheet [headers, data]

创建空 Sheet​

const emptySheet = new Sheet

从 CSV 文件导入​

Alia 支持通过 import 语句直接从 CSV 文件导入数据,自动转换为 Sheet 类型。

~ data.csv 文件内容:
~ name,age,city,score
~ Alice,30,Beijing,95
~ Bob,25,Shanghai,88
~ Charlie,35,Guangzhou,92

import 'data.csv' as sheet

print sheet.getCell at row 0 column 'name' ~ 输出 'Alice'
print sheet.getCell at row 1 column 'age' ~ 输出 30
print sheet.getCell at row 2 column 'score' ~ 输出 92

特性:

  • CSV 文件第一行自动识别为表头
  • 支持数字、布尔值(true/false,不区分大小写)和字符串的类型识别
  • 空单元格转换为 null
  • 支持引号包裹的字段(包含逗号的字段)
  • 自动处理 Windows 和 Unix 换行符

实例属性​

headers​

返回表头数组(只读)。

const sheet = new Sheet [['id', 'name', 'age'], [[1, 'Alice', 25]]]
print sheet.headers ~ 输出: ['id', 'name', 'age']

data​

返回数据二维数组(只读)。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
print sheet.data ~ 输出: [[1, 'Alice'], [2, 'Bob']]

rowMap​

返回行索引映射表(只读)。索引键以 __index_ 为前缀。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
sheet.buildIndex 'id'
print sheet.rowMap ~ 输出: [object Map]

实例方法​

getRow​

获取指定索引的行。签名为 sheet.getRow index,接收行索引并返回该行的数组副本。

const sheet = new Sheet [['id', 'name', 'age'], [[1, 'Alice', 25], [2, 'Bob', 30]]]
print sheet.getRow 0 ~ 输出: [1, 'Alice', 25]
print sheet.getRow 1 ~ 输出: [2, 'Bob', 30]

getColumn​

获取指定列名的所有数据。签名为 sheet.getColumn key,接收列名并返回该列的一维数组。

const sheet = new Sheet [['id', 'name', 'city'], [[1, 'Alice', 'Beijing'], [2, 'Bob', 'Shanghai']]]
print sheet.getColumn 'name' ~ 输出: ['Alice', 'Bob']
print sheet.getColumn 'city' ~ 输出: ['Beijing', 'Shanghai']

getCell​

获取指定单元格的值。签名为 sheet.getCell at row R column C,返回单元格的值。

const sheet = new Sheet [['id', 'name', 'age'], [[1, 'Alice', 25], [2, 'Bob', 30]]]
print sheet.getCell at row 0 column 'name' ~ 输出: 'Alice'
print sheet.getCell at row 1 column 'age' ~ 输出: 30

setCell​

设置指定单元格的值。签名为 sheet.setCell at row R column C to V,返回 Sheet 本身以支持链式调用。

const sheet = new Sheet [['id', 'name', 'city'], [[1, 'Alice', 'Beijing'], [2, 'Bob', 'Shanghai']]]
sheet.setCell at row 1 column 'city' to 'Guangzhou'
print sheet.getCell at row 1 column 'city' ~ 输出: 'Guangzhou'

appendRow​

追加一行数据。签名为 sheet.appendRow row,接收行数组并返回 Sheet 本身以支持链式调用。数组字面量实参采用 call 形式传入。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
call sheet.appendRow [[3, 'Charlie']]
print sheet.getRow 2 ~ 输出: [3, 'Charlie']

lookup​

垂直查找(sheet.lookup V returning R in M)。在 matchCol 中查找等于 value 的行,返回该行 returnCol 的值。类似 Excel 的 VLOOKUP 函数。未命中时返回 null。

const sheet = new Sheet [['id', 'name', 'city'], [[1, 'Alice', 'Beijing'], [2, 'Bob', 'Shanghai']]]

~ 根据 ID 查找城市
const city = sheet.lookup 2 returning 'city' in 'id'
print city ~ 输出: 'Shanghai'

~ 查找不存在的值返回 null
const notFound = sheet.lookup 99 returning 'city' in 'id'
print notFound ~ 输出: null

join​

表连接(users.join depts on L and R as Y)。将另一个 Sheet 根据左右列名进行连接,合并数据。as 后连接类型缺省时为内连接。

参数:

  • otherSheet: 另一个 Sheet 对象
  • leftCol(on 后): 当前 Sheet 用于连接的列名
  • rightCol(and 后): 另一个 Sheet 用于连接的列名
  • joinType(as 后): 连接类型,可选值:'inner'(默认)、'left'
~ 创建用户表
const users = new Sheet [['id', 'name', 'dept_id'], [[1, 'Alice', 101], [2, 'Bob', 102], [3, 'Charlie', 101]]]

~ 创建部门表
const depts = new Sheet [['dept_id', 'dept_name'], [[101, 'Engineering'], [102, 'Marketing'], [103, 'Sales']]]

~ 内连接
const innerJoined = users.join depts on 'dept_id' and 'dept_id' as 'inner'
print innerJoined.headers ~ 输出: ['id', 'name', 'dept_id', 'dept_name']

~ 左连接
const leftJoined = users.join depts on 'dept_id' and 'dept_id' as 'left'

groupBy​

分组映射。签名为 sheet.groupBy key with fn,按某列分组,并对每组数据执行聚合函数。聚合函数为 Alias 对象,接收每组的行数组作为参数。

参数:

  • groupCol: 用于分组的列名
  • aggFunc: 聚合函数,为 Alias 对象,接收每组的行数组作为参数
const sales = new Sheet [['product', 'region', 'amount'], [
['A', 'North', 100],
['A', 'South', 150],
['B', 'North', 80],
['B', 'South', 120],
['A', 'North', 50]
]]

~ 按产品分组,计算总销售额
const sumFunc = alias <Array rows> -> {
let sum = 0
each row in rows {
sum = sum + row[2]
}
sum
}
const totalByProduct = sales.groupBy 'product' with sumFunc

print totalByProduct ~ 输出 Sheet 表格:headers 为 ['product', 'result'],分组结果 data 为 [['A', 300], ['B', 200]]

buildIndex​

建立索引。签名为 sheet.buildIndex key,为指定列建立哈希映射,加速后续的 lookup 和 join 操作。返回 Sheet 本身以支持链式调用。

const sheet = new Sheet [['id', 'name', 'city'], [
[1, 'Alice', 'Beijing'],
[2, 'Bob', 'Shanghai'],
[3, 'Charlie', 'Guangzhou']
]]

~ 为 id 列建立索引
sheet.buildIndex 'id'

~ 后续的 lookup 操作会使用索引加速
const city = sheet.lookup 2 returning 'city' in 'id'
print city ~ 输出: 'Shanghai'

findIndexByValue​

按值查找行索引。签名为 sheet.findIndexByValue val in column col,返回首个匹配行的索引,未命中时返回 -1。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
print sheet.findIndexByValue 2 in column 'id' ~ 输出: 1
print sheet.findIndexByValue 99 in column 'id' ~ 输出: -1

toArray​

导出纯数组(包含表头)。无参数,以 call 形式调用,返回一个二维数组,第一行为表头,后续行为数据行。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
const arr = call sheet.toArray
print arr ~ 输出: [['id', 'name'], [1, 'Alice'], [2, 'Bob']]

toObject​

导出对象。无参数,以 call 形式调用,返回以行索引为键、行对象为值的对象。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
const obj = call sheet.toObject
print obj ~ 输出: *[0: *[id: 1, name: 'Alice'], 1: *[id: 2, name: 'Bob']]

clone​

深拷贝当前 Sheet。无参数,以 call 形式调用,返回一个新的 Sheet 对象,包含相同的数据但不共享引用。

const original = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
const copy = call original.clone

~ 修改副本不影响原对象
copy.setCell at row 0 column 'name' to 'Alicia'
print original.getCell at row 0 column 'name' ~ 输出: 'Alice'
print copy.getCell at row 0 column 'name' ~ 输出: 'Alicia'

toString​

返回 Sheet 的字符串表示。无参数,以 call 形式调用。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice'], [2, 'Bob']]]
print call sheet.toString
~ 输出:
~ Sheet:
~ id name
~ 1 Alice
~ 2 Bob

valueOf​

返回 Sheet 的内部值对象,包含 headers 和 data。无参数,以 call 形式调用。

const sheet = new Sheet [['id', 'name'], [[1, 'Alice']]]
print call sheet.valueOf ~ 输出: [object Object]

使用示例​

基本操作​

~ 创建 Sheet
const employees = new Sheet [['id', 'name', 'department', 'salary'], [
[1, 'Alice', 'Engineering', 8000],
[2, 'Bob', 'Marketing', 6000],
[3, 'Charlie', 'Engineering', 9000],
[4, 'David', 'Sales', 5000]
]]

~ 获取所有员工姓名
const names = employees.getColumn 'name'
print ('员工姓名: ' .. (call names.toString))

~ 获取特定员工信息
const alice = employees.getRow 0
print ('Alice 的信息: ' .. (call alice.toString))

~ 更新员工薪资
employees.setCell at row 1 column 'salary' to 6500
print ('Bob 的新薪资: ' .. (employees.getCell at row 1 column 'salary'))

~ 添加新员工
call employees.appendRow [[5, 'Eve', 'Engineering', 7500]]
print ('表格行数(含表头): ' .. ((call employees.toArray).length))

数据查找​

const products = new Sheet [['product_id', 'product_name', 'price'], [
[101, 'Laptop', 5999],
[102, 'Phone', 3999],
[103, 'Tablet', 2999],
[104, 'Headphones', 899]
]]

~ 使用 lookup 查找产品价格
const laptopPrice = products.lookup 101 returning 'price' in 'product_id'
print ('Laptop 价格: ' .. laptopPrice)

~ 建立索引加速查找
products.buildIndex 'product_id'

~ 后续查找会更快
const phonePrice = products.lookup 102 returning 'price' in 'product_id'
print ('Phone 价格: ' .. phonePrice)

~ 按值查找行索引
print products.findIndexByValue 103 in column 'product_id' ~ 输出: 2

表连接​

~ 创建订单表
const orders = new Sheet [['order_id', 'customer_id', 'amount'], [
[1, 1, 100],
[2, 2, 200],
[3, 1, 150],
[4, 3, 300]
]]

~ 创建客户表
const customers = new Sheet [['customer_id', 'customer_name', 'email'], [
[1, 'Alice', 'alice@example.com'],
[2, 'Bob', 'bob@example.com'],
[5, 'Eve', 'eve@example.com']
]]

~ 内连接:只返回匹配的记录
const orderDetails = orders.join customers on 'customer_id' and 'customer_id' as 'inner'
print '内连接结果:'
print call orderDetails.toString

~ 左连接:保留左表所有记录
const orderDetailsLeft = orders.join customers on 'customer_id' and 'customer_id' as 'left'
print '左连接结果:'
print call orderDetailsLeft.toString

分组聚合​

const salesData = new Sheet [['region', 'quarter', 'sales'], [
['North', 'Q1', 1000],
['North', 'Q2', 1200],
['South', 'Q1', 800],
['South', 'Q2', 900],
['North', 'Q3', 1100],
['South', 'Q3', 950]
]]

~ 按地区分组,计算总销售额
const sumFunc = alias <Array rows> -> {
let total = 0
each row in rows {
total = total + row[2]
}
total
}
const totalByRegion = salesData.groupBy 'region' with sumFunc

print '各地区总销售额:'
print totalByRegion

~ 按季度分组,计算平均销售额
const avgFunc = alias <Array rows> -> {
let sum = 0
each row in rows {
sum = sum + row[2]
}
sum / rows.length
}
const avgByQuarter = salesData.groupBy 'quarter' with avgFunc

print '各季度平均销售额:'
print avgByQuarter

数据导出​

const sheet = new Sheet [['id', 'name', 'email'], [
[1, 'Alice', 'alice@example.com'],
[2, 'Bob', 'bob@example.com']
]]

~ 导出为纯数组
const arr = call sheet.toArray
print '导出的数组:'
print call arr.toString

~ 导出为对象
print call sheet.toObject

~ 深拷贝
const backup = call sheet.clone
backup.setCell at row 0 column 'email' to 'alice.new@example.com'
print '原数据未被修改:'
print sheet.getCell at row 0 column 'email'

注意事项​

  1. 索引缓存: lookup 方法会自动为匹配列建立索引并缓存,后续相同列的查找会使用缓存的索引。
  2. 索引失效: 修改数据(如 setCell、appendRow)会清除所有索引缓存,需要重新建立索引。
  3. 连接类型: 当前支持 inner(内连接)和 left(左连接)两种连接类型。
  4. 聚合函数: groupBy 的聚合函数为 Alias 对象,接收每组的行数组作为参数。

下一步​