0

0

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

心靈之曲

心靈之曲

发布时间:2025-10-27 11:10:29

|

227人浏览过

|

来源于php中文网

原创

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

本文深入探讨了如何在深度嵌套的javascript对象数组中高效地查找并提取具有特定`type`属性的对象。我们将详细介绍两种主要方法:基于的迭代遍历和递归遍历,并提供迭代方法的代码示例和实现细节,帮助开发者处理复杂的json数据结构,确保能够准确、全面地筛选出所需数据。

理解复杂数据结构中的提取挑战

在现代Web应用开发中,我们经常会遇到结构复杂、层级深度不定的JSON或对象数组。例如,一个UI组件树、文档结构或配置对象,其内部可能包含多层嵌套的items数组。在这种数据结构中,如果需要找出所有具有特定属性(如type: "text")的对象,直接的filter或map方法将无法满足需求,因为它们通常只处理第一层数组。此时,我们需要更强大的遍历策略来深入到所有嵌套层级。

迭代遍历方法:利用栈实现深度优先搜索

为了有效地遍历任意深度的嵌套结构,并提取满足条件的对象,我们可以采用基于栈(Stack)的迭代方法。这种方法本质上是一种深度优先搜索(DFS)策略,它能够确保访问到所有层级的元素。

算法步骤

  1. 初始化结果数组和栈: 创建一个空数组用于存储最终匹配的对象,并创建一个栈,将原始数据数组中的所有顶层元素推入栈中。
  2. 循环遍历栈: 只要栈不为空,就持续执行以下操作:
    • 弹出当前元素: 从栈顶取出一个元素作为当前处理对象。
    • 检查元素类型: 判断当前对象的type属性是否与目标类型匹配。如果匹配,则将其添加到结果数组中。
    • 推入子元素: 如果当前对象包含一个items属性(通常是一个数组,代表其子元素),则将其所有子元素推入栈中。这一步是实现深度遍历的关键,确保在处理完当前节点的兄弟节点之前,先处理其所有子节点。
  3. 返回结果: 当栈为空时,表示所有可访问的元素都已检查完毕,返回结果数组。

代码示例

以下是使用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": 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": ["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.9195220226378, 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,则将其视为空数组,避免报错。扩展运算符...将子数组中的所有元素逐个推入栈中,而不是将整个子数组作为一个元素推入。

递归遍历方法:另一种深度优先选择

除了迭代方法,递归也是处理嵌套数据结构的经典方式。递归方法通过函数自身调用来遍历子层级。

概念

递归方法的思路是定义一个函数,该函数接收一个对象或对象数组。对于每个对象:

一览AI绘图
一览AI绘图

一览AI绘图是一览科技推出的AIGC作图工具,用AI灵感助力,轻松创作高品质图片

下载
  1. 检查其type属性是否匹配目标类型,如果匹配则添加到结果列表。
  2. 如果该对象包含items属性,则对items数组中的每个子对象递归调用自身。

优势与注意事项

  • 简洁性: 对于许多开发者而言,递归代码在表达树形或嵌套结构遍历时,逻辑可能更为直观和简洁。
  • 内存开销: 递归调用会占用调用栈(Call Stack)的内存。对于非常深层(例如几千层)的嵌套结构,可能会导致栈溢出(Stack Overflow)错误。这是递归方法的主要限制。
  • 性能: 在JavaScript引擎中,通常迭代方法的性能会略优于递归,因为它避免了函数调用的额外开销。

由于递归在概念上与迭代(使用显式栈)相似,且迭代方法在JavaScript环境中对深层嵌套的健壮性更好,因此在大多数实际场景中,迭代方法是更推荐的选择。

总结与最佳实践

从嵌套对象数组中提取特定类型元素是处理复杂数据结构的常见需求。无论是采用基于栈的迭代方法还是递归方法,核心都在于实现深度优先遍历。

  • 迭代方法(使用栈) 是处理任意深度嵌套结构的推荐方案,因为它避免了递归的栈溢出风险,并且通常在性能上具有优势。
  • 递归方法 在逻辑上可能更直观,但需要注意其潜在的栈溢出问题,尤其是在处理深度不可预测的数据时。

在实际开发中,为了提高代码的健壮性和可维护性,建议:

  • 定义清晰的类型接口(TypeScript):如示例中的Item接口,能够帮助开发者更好地理解数据结构,并在编译时捕获潜在的类型错误。
  • 错误处理与健壮性:在访问嵌套属性时,使用可选链操作符(?.)或空值合并运算符(??)可以避免因属性不存在而导致的运行时错误。
  • 考虑性能:对于非常庞大的数据集,选择合适的遍历策略至关重要。迭代方法通常是更稳健的选择。

掌握这些遍历和筛选技巧,将使您在处理各种复杂JSON和对象数据时更加得心应手。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

544

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

372

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

727

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

470

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

393

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

990

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

655

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

544

2023.09.20

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 3.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 1.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号