新闻中心
从嵌套对象数组中提取特定类型元素的教程

本文深入探讨了如何在深度嵌套的j*ascript对象数组中高效地查找并提取具有特定`type`属性的对象。我们将详细介绍两种主要方法:基于栈的迭代遍历和递归遍历,并提供迭代方法的代码示例和实现细节,帮助开发者处理复杂的json数据结构,确保能够准确、全面地筛选出所需数据。
理解复杂数据结构中的提取挑战
在现代Web应用开发中,我们经常会遇到结构复杂、层级深度不定的JSON或对象数组。例如,一个UI组件树、文档结构或配置对象,其内部可能包含多层嵌套的items数组。在这种数据结构中,如果需要找出所有具有特定属性(如type: "text")的对象,直接的filter或map方法将无法满足需求,因为它们通常只处理第一层数组。此时,我们需要更强大的遍历策略来深入到所有嵌套层级。
迭代遍历方法:利用栈实现深度优先搜索
为了有效地遍历任意深度的嵌套结构,并提取满足条件的对象,我们可以采用基于栈(Stack)的迭代方法。这种方法本质上是一种深度优先搜索(DFS)策略,它能够确保访问到所有层级的元素。
算法步骤
- 初始化结果数组和栈: 创建一个空数组用于存储最终匹配的对象,并创建一个栈,将原始数据数组中的所有顶层元素推入栈中。
-
循环遍历栈: 只要栈不为空,就持续执行以下操作:
- 弹出当前元素: 从栈顶取出一个元素作为当前处理对象。
- 检查元素类型: 判断当前对象的type属性是否与目标类型匹配。如果匹配,则将其添加到结果数组中。
- 推入子元素: 如果当前对象包含一个items属性(通常是一个数组,代表其子元素),则将其所有子元素推入栈中。这一步是实现深度遍历的关键,确保在处理完当前节点的兄弟节点之前,先处理其所有子节点。
- 返回结果: 当栈为空时,表示所有可访问的元素都已检查完毕,返回结果数组。
代码示例
以下是使用TypeScript实现此迭代方法的代码:
interface Item {
uid: string;
type: string;
items?: Item[]; // 可选的嵌套子元素数组
// ... 其他属性
}
const data: Item[] = [
{
"index": 3,
"uid": "188960ecb29_00562b0c",
"x": 18.651406278454424,
"y": 44.14920570161545,
"width": 180.14783325004774,
"height": 53.336747638012184,
"items": [
{
"uid": "18895f59b1a_2c5a5c7a",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["abc"],
"x": 154.37927087307924,
"y": 0,
"width": 25.768562376968507,
"height": 20.90412770669292,
"sampleTextChanged": true,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": fal
se,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"originalTextItem": ["abc"],
"originalXcoords": [[0, 8.25203001968504, 17.47085691437008, 25.768562376968507]]
},
{
"index": 1,
"uid": "1889607cfdf_091e59ca",
"x": 0,
"y": 32.432619931319266,
"width": 22.175427534448822,
"height": 20.90412770669292,
"items": [
{
"uid": "18895ecc7c7_2d5440b6",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["xyz"],
"x": 0,
"y": 0,
"width": 22.175427534448822,
"height": 20.90412770669292,
"sampleTextChanged": true,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"originalTextItem": ["xyz"],
"originalXcoords": [[0, 7.54406065452756, 14.95870755413386, 22.175427534448822]]
}
],
"type": "group",
"rotation": 0
},
{
"index": 2,
"uid": "188960e945c_35ab99fa",
"x": 44.108363106593984,
"y": 15.56765756703328,
"width": 56.72123163199389,
"height": 35.17448047647336,
"items": [
{
"uid": "18896072844_1298562b",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["group"],
"x": 15.567657567033265,
"y": 14.270352769780445,
"width": 41.15357406496064,
"height": 20.90412770669292,
"sampleTextChanged": true,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"originalTextItem": ["group"],
"originalXcoords": [[0, 9.013287401574805, 14.342089074803152, 23.241187869094492, 31.9195220256378, 41.15357406496064]],
"index": 2
},
{
"index": 3,
"uid": "188960e5f49_2341c362",
"x": 0,
"y": 0,
"width": 29.803226500984252,
"height": 20.90412770669292,
"items": [
{
"uid": "188958badfe_3a73220b",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["Text"],
"x": 0,
"y": 0,
"width": 29.803226500984255,
"height": 20.90412770669292,
"sampleTextChanged": false,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"istextCircularMode": false,
"originalTextItem": ["Text"],
"originalXcoords": [[0, 9.119863435039372, 17.60027066929134, 25.1443313238189, 29.803226500984255]]
}
],
"type": "group",
"rotation": 0
}
],
"type": "group",
"rotation": 0
}
],
"type": "group",
"rotation": 0
}
];
const getSpecificType = (targetType: string): Item[] => {
const result: Item[] = [];
// 使用扩展运算符将初始数据复制到栈中
const stack: Item[] = [...data];
while (stack.length > 0) {
const current = stack.pop(); // 从栈顶弹出一个元素
if (!current) continue; // 避免空值
// 检查当前元素的类型是否匹配
if (current.type === targetType) {
result.push(current);
}
// 如果当前元素有子元素(items数组),则将其所有子元素推入栈中
// 使用 ?? [] 确保即使 items 为 undefined 或 null 也能安全地扩展空数组
if (current.items && current.items.length > 0) {
stack.push(...current.items);
}
}
return result;
};
// 示例调用
const textElements = getSpecificType("text");
console.log(textElements);代码解析
- stack.pop(): 模拟栈的LIFO(后进先出)行为。每次取出最近推入的元素,这确保了深度优先的遍历顺序。
- stack.push(...current.items ?? []): 这是处理嵌套的关键。current.items可能是一个数组,也可能是undefined。?? [](空值合并运算符)确保如果current.items为null或undefined,则将其视为空数组,避免报错。扩展运算符...将子数组中的所有元素逐个推入栈中,而不是将整个子数组作为一个元素推入。
递归遍历方法:另一种深度优先选择
除了迭代方法,递归也是处理嵌套数据结构的经典方式。递归方法通过函数自身调用来遍历子层级。
概念
递归方法的思路是定义一个函数,该函数接收一个对象或对象数组。对于每个对象:
小爱开放平台
小米旗下小爱开放平台
291
查看详情
- 检查其type属性是否匹配目标类型,如果匹配则添加到结果列表。
- 如果该对象包含items属性,则对items数组中的每个子对象递归调用自身。
优势与注意事项
- 简洁性: 对于许多开发者而言,递归代码在表达树形或嵌套结构遍历时,逻辑可能更为直观和简洁。
- 内存开销: 递归调用会占用调用栈(Call Stack)的内存。对于非常深层(例如几千层)的嵌套结构,可能会导致栈溢出(Stack Overflow)错误。这是递归方法的主要限制。
- 性能: 在J*aScript引擎中,通常迭代方法的性能会略优于递归,因为它避免了函数调用的额外开销。
由于递归在概念上与迭代(使用显式栈)相似,且迭代方法在J*aScript环境中对深层嵌套的健壮性更好,因此在大多数实际场景中,迭代方法是更推荐的选择。
总结与最佳实践
从嵌套对象数组中提取特定类型元素是处理复杂数据结构的常见需求。无论是采用基于栈的迭代方法还是递归方法,核心都在于实现深度优先遍历。
- 迭代方法(使用栈) 是处理任意深度嵌套结构的推荐方案,因为它避免了递归的栈溢出风险,并且通常在性能上具有优势。
- 递归方法 在逻辑上可能更直观,但需要注意其潜在的栈溢出问题,尤其是在处理深度不可预测的数据时。
在实际开发中,为了提高代码的健壮性和可维护性,建议:
- 定义清晰的类型接口(TypeScript):如示例中的Item接口,能够帮助开发者更好地理解数据结构,并在编译时捕获潜在的类型错误。
- 错误处理与健壮性:在访问嵌套属性时,使用可选链操作符(?.)或空值合并运算符(??)可以避免因属性不存在而导致的运行时错误。
- 考虑性能:对于非常庞大的数据集,选择合适的遍历策略至关重要。迭代方法通常是更稳健的选择。
掌握这些遍历和筛选技巧,将使您在处理各种复杂JSON和对象数据时更加得心应手。
以上就是从嵌套对象数组中提取特定类型元素的教程的详细内容,更多请关注其它相关文章!
# java
# javascript
# 递归
# red
# overflow
# 应用开发
# 栈
# typescript
# json
# js
# 沈河区网站建设活动方案
# 文山网站建设机构有哪些
# 浏阳怎么做营销推广
# 武汉关键词排名推荐乐云seo品牌
# 成安邯郸企业做网站推广
# 海外营销推广背景分析
# 智能全网营销引流推广策略
# 定制化 网站建设流程
# 广西网站建设制作费用
# 营销推广页图片素材
# 是一个
# 则将
# 小爱
# 可选
# 运算符
# 组中
# 迭代
# 数据结构
# 遍历
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
12306选座怎么选到特殊座位_12306特殊座位选择注意事项
特斯拉自动驾驶房车计划曝光 原型车将于2027年亮相
Python vgamepad库按键模拟:正确使用XUSB_BUTTON常量
vivo云服务网页版登录 怎么登录vivo云服务网页版
从OpenAI API响应中高效提取生成文本
2025俄罗斯Yandex最新入口 官方网站地址及浏览器下载指南
J*aScript动态修改指定div内所有a标签样式指南
win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】
Python类型检查:优化关联可选属性的Mypy推断策略
TikTok国际版官网直达_TikTok国际版官网直达进入在线观看
一加Ace 6T实拍样张首次公布!李杰:主摄实力完全看齐4K档性能旗舰
怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法
Web Components中自定义开关组件状态同步的常见陷阱与解决方案
AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看
马斯克:Optimus 人形机器人复数形式为 Optimi
夸克浏览器图书入口 夸克手机浏览器阅读入口
Win10如何恢复误删的快捷方式_Win10重建常用软件快捷方式
NVIDIA股价11月重挫12%:下月有望好转 但难回5万亿美元巅峰
漫蛙漫画官方首页 漫蛙2漫画在线阅读入口
Composer中的^和~符号代表什么_精通Composer版本号语义化约束
c++如何实现一个简单的软件渲染器_c++从零开始的3D图形学
在Blazor WebAssembly应用中动态注入客户端特定指标代码的策略
优化Log4j2控制台输出性能:解决异步日志瓶颈
Win11 USB传输速度慢怎么解决 Win11 USB驱动更新与设置
Flexbox布局实践:实现粘性导航栏与底部固定页脚
J*a递归快速排序中静态变量导致数据累积的陷阱与解决方案
LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读
谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法
在J*aScript中复现SciPy的B样条拟合与求值:关键考量
CSS图片焦点样式实现教程:理解与应用tabindex属性
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
Archive of Our Own官网直达 AO3最新可用地址一览
AO3最新入口2025公告_AO3中文官网合集
Win11如何开启讲述人功能 Win11屏幕阅读器(讲述人)开启与关闭【教程】
AngularJS $http POST请求数据传递与Go后端接收实践
Google翻译怎么语音输入_Google翻译语音输入功能使用与设置方法
《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!
在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案
微博网页版主页入口 微博官方网站免登录访问
Selenium Python中处理点击后新窗口加载冻结问题的策略与实践
漫画星球免费下拉式入口 漫画星球免费漫画在线阅读网站
一加手机电池耗电快怎么办_一加手机电池耗电快的解决方法
必由学官网快捷入口 必由学网页版在线学习平台
新手怎么开始学化妆 零基础化妆入门教程
蛙漫漫画官网在线入口 蛙漫全本漫画免费阅读平台
一加 14R 快充无反应_一加 14R 充电优化
Django AJAX 文件上传教程:解决图片无法保存到模型的常见问题
利用Bokeh CustomJS动态控制DataTable列可见性
php源码怎么看淘宝客系统_看php源码淘宝客系统技巧
抖音创作助手登录入口_抖音创作辅助工具官网直达


2025-10-27
浏览次数:次
返回列表
se,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"originalTextItem": ["abc"],
"originalXcoords": [[0, 8.25203001968504, 17.47085691437008, 25.768562376968507]]
},
{
"index": 1,
"uid": "1889607cfdf_091e59ca",
"x": 0,
"y": 32.432619931319266,
"width": 22.175427534448822,
"height": 20.90412770669292,
"items": [
{
"uid": "18895ecc7c7_2d5440b6",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["xyz"],
"x": 0,
"y": 0,
"width": 22.175427534448822,
"height": 20.90412770669292,
"sampleTextChanged": true,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"originalTextItem": ["xyz"],
"originalXcoords": [[0, 7.54406065452756, 14.95870755413386, 22.175427534448822]]
}
],
"type": "group",
"rotation": 0
},
{
"index": 2,
"uid": "188960e945c_35ab99fa",
"x": 44.108363106593984,
"y": 15.56765756703328,
"width": 56.72123163199389,
"height": 35.17448047647336,
"items": [
{
"uid": "18896072844_1298562b",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["group"],
"x": 15.567657567033265,
"y": 14.270352769780445,
"width": 41.15357406496064,
"height": 20.90412770669292,
"sampleTextChanged": true,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"originalTextItem": ["group"],
"originalXcoords": [[0, 9.013287401574805, 14.342089074803152, 23.241187869094492, 31.9195220256378, 41.15357406496064]],
"index": 2
},
{
"index": 3,
"uid": "188960e5f49_2341c362",
"x": 0,
"y": 0,
"width": 29.803226500984252,
"height": 20.90412770669292,
"items": [
{
"uid": "188958badfe_3a73220b",
"locked": false,
"rotation": 0,
"type": "text",
"text": ["Text"],
"x": 0,
"y": 0,
"width": 29.803226500984255,
"height": 20.90412770669292,
"sampleTextChanged": false,
"fontSize": 15.590551181102365,
"fontFamily": "NimbusSansME",
"textBold": false,
"textItalic": false,
"textUnderline": false,
"textAlignment": "TEXT_ALIGN_LEFT",
"textLetterSpacing": 0,
"color": { "red": 0, "green": 0, "blue": 0, "__class__": "RGBAColor", "alpha": 1 },
"placeholderText": ["Text"],
"isPlaceholderTextActive": false,
"translationKey": "",
"newPathCalculation": true,
"shadow": { "blur": 0, "color": "{\"red\":255,\"green\":255,\"blue\":255,\"transparent\":0}", "coords": { "x": 0, "y": 0 }, "distance": 0, "opacity": 1 },
"index": 0,
"istextCircularMode": false,
"originalTextItem": ["Text"],
"originalXcoords": [[0, 9.119863435039372, 17.60027066929134, 25.1443313238189, 29.803226500984255]]
}
],
"type": "group",
"rotation": 0
}
],
"type": "group",
"rotation": 0
}
],
"type": "group",
"rotation": 0
}
];
const getSpecificType = (targetType: string): Item[] => {
const result: Item[] = [];
// 使用扩展运算符将初始数据复制到栈中
const stack: Item[] = [...data];
while (stack.length > 0) {
const current = stack.pop(); // 从栈顶弹出一个元素
if (!current) continue; // 避免空值
// 检查当前元素的类型是否匹配
if (current.type === targetType) {
result.push(current);
}
// 如果当前元素有子元素(items数组),则将其所有子元素推入栈中
// 使用 ?? [] 确保即使 items 为 undefined 或 null 也能安全地扩展空数组
if (current.items && current.items.length > 0) {
stack.push(...current.items);
}
}
return result;
};
// 示例调用
const textElements = getSpecificType("text");
console.log(textElements);