- 什么是字典(Dictionary)
- 字典积木块概览
- 创建字典
- 添加和修改键值对
- 获取值
- 删除键值对
- 遍历字典
- 嵌套字典
- 字典与列表转换
- 复制和合并字典
- 高级遍历:walk key path
- 判断数据类型:is a dictionary?
- 字典在JSON解析中的应用
- 实战案例一:学生成绩管理
- 实战案例二:购物车数据结构
- 字典操作速查表
- 常见问题
- 总结
什么是字典(Dictionary)
字典(Dictionary)是一种键值对(Key-Value Pair)数据结构,它通过唯一的”键”来关联对应的”值”。在其他编程语言中,字典也被称为映射(Map)、关联数组(Associative Array)或哈希表(HashMap)。
打个比方:字典就像一本电话簿,”姓名”是键,”电话号码”是值。你不需要记住电话号码在第几页(不需要索引),只需通过姓名就能找到对应的号码。
字典 vs 列表
| 特性 | 列表(List) | 字典(Dictionary) |
|---|---|---|
| 访问方式 | 通过索引(数字位置) | 通过键(文本或其他类型) |
| 顺序 | 有序 | 无序 |
| 适用场景 | 有序数据集合 | 需要通过名称快速查找数据 |
| 示例 | ["苹果", "香蕉", "橙子"] |
{"name": "小明", "age": 12} |
| 查找效率 | 需遍历 | 直接通过键查找,效率高 |
JSON与字典的关系
JSON(JavaScript Object Notation)中的对象({})在App Inventor中就是字典,JSON中的数组([])对应列表。
{
"id": 1,
"name": "Tim the Beaver",
"school": {
"name": "Massachusetts Institute of Technology"
},
"enrolled": true,
"classes": ["6.001", "18.01", "8.01"]
}
上面的JSON数据中,键可以是文本、数字、布尔值,值可以是任何类型(文本、数字、布尔值、字典、列表)。
字典积木块概览
App Inventor 2 中的字典积木块位于「内置块 → 字典」类别中,共提供以下积木块:
| 积木块 | 功能 |
|---|---|
create empty dictionary |
创建空字典 |
make a dictionary |
用键值对创建字典 |
pair |
构造键值对 |
get value for key |
根据键获取值 |
set value for key |
设置/添加键值对 |
delete entry for key |
删除键值对 |
get value at key path |
沿路径获取嵌套值 |
set value for key path |
沿路径设置嵌套值 |
get keys |
获取所有键的列表 |
get values |
获取所有值的列表 |
is key in dictionary? |
判断键是否存在 |
size of dictionary |
获取键值对数量 |
list of pairs to dictionary |
关联列表转字典 |
dictionary to list of pairs |
字典转关联列表 |
copy dictionary |
深拷贝字典 |
merge into dictionary |
合并字典 |
list by walking key path |
沿路径收集值列表 |
walk all at level |
遍历当前层所有元素 |
is a dictionary? |
判断是否为字典 |
创建字典
方法一:create empty dictionary(创建空字典)
创建一个没有任何键值对的空字典,后续可通过 set value for key 添加数据。
设 变量 myDict 为 create empty dictionary
// myDict = {}(空字典)
使用场景: 当字典的内容需要在程序运行过程中动态添加时,先创建一个空字典。
方法二:make a dictionary + pair(直接创建含数据的字典)
如果预先知道字典的内容,可以用 make a dictionary 结合 pair 积木块直接创建:
设 变量 student 为 make a dictionary
pair("name", "小明")
pair("age", 12)
pair("grade", "六年级")
// student = {"name": "小明", "age": 12, "grade": "六年级"}
说明: pair 积木块专门用于构造键值对,只能在 make a dictionary 内部使用。点击 make a dictionary 积木块上的蓝色齿轮图标,可以添加更多的 pair 条目。
提示: create empty dictionary 积木块也可以通过点击蓝色齿轮按钮添加 pair 条目,将其变为 make a dictionary 积木块。
添加和修改键值对
set value for key(设置键值对)
这是向字典中添加新键值对或修改已有键值对的核心积木块。
// 添加新的键值对
set value for key "name" in dictionary myDict to "小红"
// 添加更多键值对
set value for key "age" in dictionary myDict to 13
set value for key "score" in dictionary myDict to 95.5
// myDict = {"name": "小红", "age": 13, "score": 95.5}
行为说明:
- 如果字典中不存在该键,则新建一个键值对
- 如果字典中已存在该键,则替换原来的值
// 修改已有键值对
set value for key "name" in dictionary myDict to "小刚"
// myDict = {"name": "小刚", "age": 13, "score": 95.5}
从2个键值对增加到3个或更多
用户经常问:”字典里已经有2个键值对,如何增加到3个?”答案是使用 set value for key 动态添加:
// 假设已有字典: {"name": "小明", "age": 12}
// 要增加第3个键值对:
set value for key "grade" in dictionary student to "六年级"
// 现在 student = {"name": "小明", "age": 12, "grade": "六年级"}
// 继续增加更多:
set value for key "school" in dictionary student to "实验小学"
set value for key "hobby" in dictionary student to "编程"
核心要点: 字典的键值对数量没有上限,随时可以通过 set value for key 添加新的键值对。
获取值
get value for key(根据键获取值)
通过键名获取字典中对应的值:
设 变量 name 为 get value for key "name" from dictionary myDict
// 如果 myDict = {"name": "小明", "age": 12},则 name = "小明"
// 如果键不存在,返回 "not found" 参数的默认值
设 变量 email 为 get value for key "email" from dictionary myDict
not found: "无邮箱"
// email = "无邮箱"(因为字典中没有 "email" 键)
行为说明: 如果字典中存在该键,返回对应的值;如果不存在,返回 not found 参数指定的默认值。
get value at key path(沿路径获取嵌套值)
对于多层嵌套的数据结构,可以使用 get value at key path 通过路径一次性获取深层值。
// 假设有嵌套字典:
// student = {
// "name": "小明",
// "school": {
// "name": "实验小学",
// "city": "北京"
// }
// }
// 获取学校名称 - 逐层获取:
设 变量 schoolName 为 get value at key path
path: make a list("school", "name")
from dictionary: student
// schoolName = "实验小学"
路径中可以混合使用键名和数字索引:
// 假设有混合数据:
// data = {
// "name": "Tim",
// "classes": ["6.001", "18.01", "8.01"]
// }
// 获取第二门课程(索引从1开始)
设 变量 secondClass 为 get value at key path
path: make a list("classes", 2)
from dictionary: data
// secondClass = "18.01"
说明: get value for key 等价于 get value at key path 的路径长度为1的情况。当路径中遇到字典时使用键名,遇到列表时使用数字索引。
set value for key path(沿路径设置嵌套值)
与 get value at key path 互为镜像操作,用于更新嵌套结构中的值:
// 修改嵌套字典中的学校名称
set value for key path
path: make a list("school", "name")
in dictionary: student
to value: "第一中学"
行为说明:
- 路径必须有效,但最后一个键可以不存在
- 如果最后一个键不存在,会创建新的键值对
- 如果最后一个键已存在,会替换原来的值
删除键值对
delete entry for key(删除指定键的条目)
// 假设 myDict = {"name": "小明", "age": 12, "grade": "六年级"}
delete entry for key "age" from dictionary myDict
// myDict = {"name": "小明", "grade": "六年级"}
// 如果键不存在,字典不受影响
delete entry for key "email" from dictionary myDict
// myDict 不变
行为说明: 删除字典中指定键对应的键值对。如果键不存在,字典不做任何修改。
遍历字典
获取所有键:get keys
设 变量 allKeys 为 get keys from dictionary myDict
// 如果 myDict = {"name": "小明", "age": 12},则 allKeys = ["name", "age"]
获取所有值:get values
设 变量 allValues 为 get values from dictionary myDict
// 如果 myDict = {"name": "小明", "age": 12},则 allValues = ["小明", 12]
注意: get values 返回的列表中的值与字典中的值是引用关系。修改列表中的值(如果值本身是字典或列表),也会同步修改字典中的值。
使用 for each 循环遍历字典
通过 get keys 获取所有键,再用循环遍历:
设 变量 myDict 为 make a dictionary
pair("语文", 92)
pair("数学", 88)
pair("英语", 95)
设 变量 keys 为 get keys from dictionary myDict
for each item key in list keys do:
设 变量 value 为 get value for key key from dictionary myDict
设置 Label1.文本 为 join(Label1.文本, "\n", key, ": ", value)
// 输出:
// 语文: 92
// 数学: 88
// 英语: 95
判断键是否存在:is key in dictionary?
如果 is key in dictionary? key: "email" in dictionary myDict 则
设置 Label1.文本 为 get value for key "email" from dictionary myDict
否则
设置 Label1.文本 为 "未设置邮箱"
获取键值对数量:size of dictionary
设 变量 count 为 size of dictionary myDict
// 如果 myDict = {"name": "小明", "age": 12},则 count = 2
嵌套字典
字典的值可以是另一个字典,形成多层嵌套结构。这在处理复杂JSON数据时非常常见。
设 变量 student 为 make a dictionary
pair("name", "小明")
pair("contact", make a dictionary
pair("phone", "13800138000")
pair("email", "xiaoming@example.com")
)
pair("address", make a dictionary
pair("city", "北京")
pair("district", "海淀区")
pair("street", "中关村大街1号")
)
访问嵌套字典中的值有两种方式:
方式一:逐层获取
设 变量 contact 为 get value for key "contact" from dictionary student
设 变量 phone 为 get value for key "phone" from dictionary contact
// phone = "13800138000"
方式二:使用 key path 一次性获取
设 变量 phone 为 get value at key path
path: make a list("contact", "phone")
from dictionary: student
// phone = "13800138000"
推荐使用方式二,代码更简洁高效。
字典与列表转换
list of pairs to dictionary(关联列表转字典)
将形如 ((key1 value1) (key2 value2) ...) 的关联列表转换为字典:
设 变量 pairList 为 make a list
make a list("name", "小明")
make a list("age", 12)
make a list("grade", "六年级")
设 变量 myDict 为 list of pairs to dictionary pairList
// myDict = {"name": "小明", "age": 12, "grade": "六年级"}
为什么要转换? 字典的查找效率比关联列表高。如果你需要对一个关联列表进行大量查找操作,建议先转换为字典。
dictionary to list of pairs(字典转关联列表)
将字典转换为关联列表,这是 list of pairs to dictionary 的逆操作:
设 变量 myDict 为 make a dictionary
pair("name", "小明")
pair("age", 12)
设 变量 pairList 为 dictionary to list of pairs myDict
// pairList = (("name" "小明") ("age" 12))
这两个操作互为逆操作,可以互相转换:
设 变量 original 为 make a dictionary pair("a", 1) pair("b", 2)
设 变量 pairs 为 dictionary to list of pairs original
设 变量 restored 为 list of pairs to dictionary pairs
// restored 和 original 内容相同
复制和合并字典
copy dictionary(深拷贝字典)
设 变量 original 为 make a dictionary
pair("name", "小明")
pair("scores", make a list(90, 85, 92))
设 变量 copied 为 copy dictionary original
// 修改副本不会影响原字典
set value for key "name" in dictionary copied to "小红"
// original.name 仍然是 "小明"
// copied.name 变为 "小红"
重要: copy dictionary 执行的是深拷贝(deep copy),即所有值都会被递归复制。修改副本中的任何值(包括嵌套的字典或列表)都不会影响原字典。
merge into dictionary(合并字典)
将一个字典的键值对复制到另一个字典中:
设 变量 defaults 为 make a dictionary
pair("theme", "light")
pair("language", "zh")
pair("fontSize", 14)
设 变量 userPrefs 为 make a dictionary
pair("language", "en")
pair("fontSize", 16)
merge into dictionary from dictionary userPrefs into dictionary defaults
// defaults = {"theme": "light", "language": "en", "fontSize": 16}
// 注意:"language" 和 "fontSize" 被用户设置覆盖了
行为说明: 如果源字典和目标字典有相同的键,目标字典中的值会被源字典的值覆盖。
高级遍历:walk key path
list by walking key path(沿路径收集值)
这是最强大的字典操作积木块之一,用于从复杂嵌套结构中批量提取数据。它的工作原理类似 get value at key path,但返回的是一个值列表而不是单个值。
路径中可以包含三种类型的元素:
- 字典键 — 沿指定键路径前进
- 数字索引 — 沿列表指定位置前进
- walk all at level — 遍历当前层的所有元素
示例:从嵌套数据中提取所有人的名字
假设有以下JSON数据:
{
"people": [
{"first_name": "Tim", "last_name": "Beaver"},
{"first_name": "John", "last_name": "Smith"},
{"first_name": "Jane", "last_name": "Doe"}
]
}
获取所有人的 first_name:
设 变量 data 为 {上述JSON解析后的字典}
设 变量 firstNames 为 list by walking key path
from dictionary: data
path: make a list("people", walk all at level, "first_name")
// firstNames = ["Tim", "John", "Jane"]
路径解析过程:
"people"— 进入people键对应的列表walk all at level— 遍历列表中的每一个元素(每个人)"first_name"— 获取每个人的first_name值
walk all at level(遍历当前层)
walk all at level 只能在 list by walking key path 的路径中使用,表示遍历当前位置的所有元素:
- 如果当前位置是字典,遍历字典中所有的值
- 如果当前位置是列表,遍历列表中所有的元素
复杂示例:提取所有课程名称
{
"departments": [
{
"name": "计算机系",
"courses": [
{"title": "Python入门", "credits": 3},
{"title": "数据结构", "credits": 4}
]
},
{
"name": "数学系",
"courses": [
{"title": "微积分", "credits": 4},
{"title": "线性代数", "credits": 3}
]
}
]
}
设 变量 allTitles 为 list by walking key path
from dictionary: data
path: make a list("departments", walk all at level, "courses", walk all at level, "title")
// allTitles = ["Python入门", "数据结构", "微积分", "线性代数"]
判断数据类型:is a dictionary?
如果 is a dictionary? myData 则
设置 Label1.文本 为 "这是一个字典,包含 " & (size of dictionary myData) & " 个键值对"
否则 如果 is a list? myData 则
设置 Label1.文本 为 "这是一个列表,包含 " & (length of list myData) & " 个元素"
否则
设置 Label1.文本 为 "这是一个普通值"
使用场景: 当从Web API获取数据后,不确定返回的是字典还是列表时,可以用 is a dictionary? 进行判断。
字典在JSON解析中的应用
字典是App Inventor中处理JSON数据的核心工具。JSON解析后的对象会自动转换为字典。
解析JSON字符串
当 Web1.GotText 执行时:
设 变量 responseCode 为 responseCode
设 变量 responseContent 为 responseContent
如果 responseCode = 200 则
// 将JSON文本解析为字典
设 变量 data 为 call Web1.JsonTextDecodeWithDictionaries(responseContent)
// 从字典中提取数据
设 变量 name 为 get value for key "name" from dictionary data
设置 Label1.文本 为 name
解析嵌套JSON
// JSON: {"user": {"profile": {"avatar": "https://..."}}}
设 变量 avatar 为 get value at key path
path: make a list("user", "profile", "avatar")
from dictionary: data
解析JSON数组中的对象
// JSON: {"results": [{"name": "A"}, {"name": "B"}]}
设 变量 results 为 get value for key "results" from dictionary data
for each item item in list results do:
设 变量 name 为 get value for key "name" from dictionary item
设置 ListPicker1.元素 为 join(ListPicker1.元素, name, ",")
实战案例一:学生成绩管理
使用字典管理多名学生的成绩数据。
数据结构设计
设 全局变量 students 为 create empty dictionary
// 每个学生的数据用嵌套字典表示:
// {
// "stu001": {"name": "小明", "math": 92, "chinese": 88, "english": 95},
// "stu002": {"name": "小红", "math": 98, "chinese": 91, "english": 87},
// "stu003": {"name": "小刚", "math": 85, "chinese": 93, "english": 90}
// }
添加学生
// 添加一个新学生
设 变量 newStudent 为 make a dictionary
pair("name", "小明")
pair("math", 92)
pair("chinese", 88)
pair("english", 95)
set value for key "stu001" in dictionary students to newStudent
查询学生成绩
设 变量 stuId 为 TextBox1.文本 // 用户输入学号,如 "stu001"
如果 is key in dictionary? key: stuId in dictionary students 则
设 变量 student 为 get value for key stuId from dictionary students
设 变量 name 为 get value for key "name" from dictionary student
设 变量 math 为 get value for key "math" from dictionary student
设 变量 chinese 为 get value for key "chinese" from dictionary student
设 变量 english 为 get value for key "english" from dictionary student
设 变量 total 为 math + chinese + english
设 变量 average 为 total / 3
设置 Label1.文本 为 join("姓名: ", name, "\n",
"数学: ", math, "\n",
"语文: ", chinese, "\n",
"英语: ", english, "\n",
"总分: ", total, "\n",
"平均分: ", format as decimal(average, 1))
否则
设置 Label1.文本 为 "未找到该学号的学生"
修改学生成绩
设 变量 stuId 为 "stu001"
设 变量 student 为 get value for key stuId from dictionary students
set value for key "math" in dictionary student to 95
// 由于 student 是字典中的引用,修改会直接生效
删除学生
delete entry for key "stu001" from dictionary students
显示所有学生名单
设 变量 ids 为 get keys from dictionary students
设 变量 result 为 ""
for each item id in list ids do:
设 变量 student 为 get value for key id from dictionary students
设 变量 name 为 get value for key "name" from dictionary student
设 变量 result 为 join(result, id, " - ", name, "\n")
设置 Label1.文本 为 result
实战案例二:购物车数据结构
使用字典+列表的组合构建购物车功能。
数据结构设计
// 购物车字典:
// {
// "items": [
// {"id": "p001", "name": "苹果", "price": 5.5, "quantity": 3},
// {"id": "p002", "name": "牛奶", "price": 12.0, "quantity": 2}
// ],
// "totalPrice": 40.5,
// "totalCount": 5
// }
设 全局变量 cart 为 make a dictionary
pair("items", create empty list)
pair("totalPrice", 0)
pair("totalCount", 0)
添加商品到购物车
设 变量 productId 为 "p001"
设 变量 productName 为 "苹果"
设 变量 productPrice 为 5.5
// 检查购物车中是否已有该商品
设 变量 items 为 get value for key "items" from dictionary cart
设 变量 found 为 false
设 变量 foundIndex 为 0
for each item item in list items do:
设 变量 id 为 get value for key "id" from dictionary item
如果 id = productId 则
设 变量 found 为 true
如果 found 则
// 商品已在购物车中,数量+1
// (需要找到该商品并更新数量)
for each item item in list items do:
设 变量 id 为 get value for key "id" from dictionary item
如果 id = productId 则
设 变量 qty 为 get value for key "quantity" from dictionary item
set value for key "quantity" in dictionary item to qty + 1
否则
// 新商品,添加到购物车
设 变量 newItem 为 make a dictionary
pair("id", productId)
pair("name", productName)
pair("price", productPrice)
pair("quantity", 1)
add items to list
list: get value for key "items" from dictionary cart
item: newItem
// 更新总价和总数量
call 更新购物车统计
更新购物车统计
过程 更新购物车统计:
设 变量 items 为 get value for key "items" from dictionary cart
设 变量 totalPrice 为 0
设 变量 totalCount 为 0
for each item item in list items do:
设 变量 price 为 get value for key "price" from dictionary item
设 变量 qty 为 get value for key "quantity" from dictionary item
设 变量 totalPrice 为 totalPrice + price * qty
设 变量 totalCount 为 totalCount + qty
set value for key "totalPrice" in dictionary cart to totalPrice
set value for key "totalCount" in dictionary cart to totalCount
设置 TotalLabel.文本 为 join("合计: ¥", format as decimal(totalPrice, 2))
设置 CountLabel.文本 为 join("共 ", totalCount, " 件商品")
从购物车移除商品
设 变量 items 为 get value for key "items" from dictionary cart
设 变量 newItems 为 create empty list
for each item item in list items do:
设 变量 id 为 get value for key "id" from dictionary item
如果 id ≠ 要删除的商品ID 则
add items to list
list: newItems
item: item
set value for key "items" in dictionary cart to newItems
call 更新购物车统计
显示购物车内容
设 变量 items 为 get value for key "items" from dictionary cart
设 变量 display 为 ""
for each item item in list items do:
设 变量 name 为 get value for key "name" from dictionary item
设 变量 price 为 get value for key "price" from dictionary item
设 变量 qty 为 get value for key "quantity" from dictionary item
设 变量 subtotal 为 price * qty
设 变量 display 为 join(display, name,
" x", qty,
" ¥", format as decimal(subtotal, 2),
"\n")
设置 CartLabel.文本 为 display
call 更新购物车统计
字典操作速查表
| 操作 | 积木块 | 说明 |
|---|---|---|
| 创建空字典 | create empty dictionary |
后续动态添加键值对 |
| 创建有数据的字典 | make a dictionary + pair |
初始化时已知键值对 |
| 添加/修改键值对 | set value for key |
键不存在则新建,存在则替换 |
| 获取值 | get value for key |
键不存在返回默认值 |
| 获取嵌套值 | get value at key path |
支持多层路径和数字索引 |
| 设置嵌套值 | set value for key path |
路径需有效,最后键可不存在 |
| 删除键值对 | delete entry for key |
键不存在则无操作 |
| 获取所有键 | get keys |
返回键的列表 |
| 获取所有值 | get values |
返回值的列表(引用) |
| 判断键是否存在 | is key in dictionary? |
返回 true/false |
| 获取大小 | size of dictionary |
返回键值对数量 |
| 列表转字典 | list of pairs to dictionary |
提升查找效率 |
| 字典转列表 | dictionary to list of pairs |
互转操作 |
| 深拷贝 | copy dictionary |
修改副本不影响原字典 |
| 合并 | merge into dictionary |
源字典覆盖目标字典同键 |
| 批量提取 | list by walking key path |
支持路径 + walk all |
| 遍历所有 | walk all at level |
配合 walking key path |
| 类型判断 | is a dictionary? |
区分字典和列表 |
常见问题
1. 字典和列表怎么选择?
- 需要通过名称查找数据 → 用字典
- 数据有固定顺序 → 用列表
- 需要判断某个标识是否存在 → 用字典
- 需要按序号逐一处理 → 用列表
2. 键可以是数字吗?
可以。字典的键不限于文本,也可以是数字。但在 get value at key path 的路径中,数字会被解释为列表索引。如果需要用数字作为字典的键,建议使用 get value for key 而非 get value at key path。
3. 字典中同一个键可以有多个值吗?
不可以。字典中每个键只能对应一个值。如果需要存储多个值,可以将值设为一个列表:
设 变量 student 为 make a dictionary
pair("name", "小明")
pair("courses", make a list("数学", "语文", "英语"))
4. get values 返回的列表修改后会影响字典吗?
是的。get values 返回的是字典中值的引用。如果值本身是字典或列表,通过返回列表修改它,字典中的数据也会同步改变。如果不希望互相影响,请使用 copy dictionary 创建副本。
5. 如何调试字典内容?
// 方法一:转为文本查看
设置 DebugLabel.文本 为 join("键: ", get keys from dictionary myDict)
设置 DebugLabel.文本 为 join("值: ", get values from dictionary myDict)
// 方法二:查看大小
设置 DebugLabel.文本 为 join("键值对数量: ", size of dictionary myDict)
// 方法三:检查类型
如果 is a dictionary? myData 则
设置 DebugLabel.文本 为 "这是一个字典"
否则 如果 is a list? myData 则
设置 DebugLabel.文本 为 "这是一个列表"
总结
字典是App Inventor 2中处理结构化数据的核心工具,特别适合以下场景:
- JSON数据解析 — API返回的JSON对象就是字典
- 配置信息存储 — 用键名快速查找配置项
- 数据映射关系 — 通过唯一标识关联详细信息
- 复杂嵌套数据 — 字典和列表的组合处理多层结构
掌握字典的创建、增删改查、遍历和嵌套操作,是使用App Inventor 2进行高级开发的基础能力。
本文参考了 MIT App Inventor官方文档 - Dictionary Blocks 编写。
© 2025 AppInventor2中文网. 本教程基于 MIT App Inventor 官方文档编写,遵循 Creative Commons Attribution-ShareAlike 4.0 International License 协议。
扫码添加客服咨询