【问题标题】:What is the most elegant way to display key value pairs using a recursive function with JavaScript?使用带有 JavaScript 的递归函数来显示键值对的最优雅的方式是什么?
【发布时间】:2020-11-18 06:18:15
【问题描述】:

如何循环遍历包含未知数量的嵌套对象、字符串或数组的对象。结构类似于:

const myObject = {
    name: 'Dan',
    age: 31,
    interests: ['coding', 'asking questions'],
    needsHelp: true,
    nestedData: {
        level1Data: {
            randomNumber: 41,
            anObject: {
                description: 'Nested data'
            }
        }
    }
};

我目前正在为循环使用这样的函数:

for (var k in obj) {
  // If object and its not empty
  if (typeof obj[k] == "object" && obj[k] !== null) {
    // Run function again
    eachRecursive(obj[k]);
  }
  // if something else and not empty
  else {
    if (obj[k] !== null) {
      console.log(typeof obj[k], obj[k]);
    }
  }
}

这个函数循环我想要的方式,但是我想在一个表格结构中列出这些,其中深层嵌套数组/对象是我需要一些帮助来弄清楚的步骤。

我想输出的 HTML 表格的示例在下面的屏幕截图中:

【问题讨论】:

  • 你有给定对象想要的结果的例子吗?
  • “以表格结构列出这些”你能把它的样子写下来吗?
  • 你可能不想在你的问题中使用“大多数”这个词,因为可能没有一个我们都会同意的答案,这意味着你的问题可能会因为基于意见而被关闭。
  • 感谢您的反馈,我将编辑和整理所需的输出以使这个问题更清楚。
  • @NinaScholz 我已经添加了所需的输出表。

标签: javascript arrays loops recursion javascript-objects


【解决方案1】:

您可以将额外的prefix 参数传递给每个递归调用并将其附加到嵌套键。 flatMap 用于获取条目的平面数组,而不是嵌套数组。

遍历返回的条目并创建表的行

由于您希望整个数组位于一行中,因此添加了!Array.isArray(v) 条件。如果您有对象数组作为属性,则可以从 if 条件中跳过它

const myObject = { name: 'Dan', age: 31, interests: ['coding', 'asking questions'], needsHelp: true, nestedData: { level1Data: { randomNumber: 41, anObject: { description: 'Nested data' } } } };

function getEntries(obj, prefix = '') {
  return Object.entries(obj).flatMap(([k, v]) => {
    // if nested values is an object and it is not an array
    if (Object(v) === v && !Array.isArray(v))
      return getEntries(v, `${prefix}${k}.`)
    else
      return [ [`${prefix}${k}`, v] ]
  })
}

/*
console.log( JSON.stringify(getEntries(myObject)) )

// if you want to create a flat object
console.log( 
 Object.fromEntries(getEntries(myObject)) 
)
*/

// creating rows of the table
getEntries(myObject).forEach(([k, v]) => {
  document.querySelector("table").innerHTML +=
  `<tr>
    <td>${k}</td>
    <td>${v}</td>
  </tr>`
})
table, th, td {
  border: 1px solid black;
}
&lt;table&gt;&lt;/table&gt;

【讨论】:

  • 这很棒,我可以使用它并很容易地修改输出。
【解决方案2】:

您可以通过数组中的值获取完整路径。

基本上,它需要检查是否有 truthy 值和对象类型但不是数组,然后获取条目并返回连接键和最终值的数组。

或者返回一个只包含空字符串和值的嵌套数组的数组。

空字符串控制更多键的分隔点。

const
    getPath = value => value && typeof value === 'object' && !Array.isArray(value)
        ? Object
            .entries(value)
            .reduce((r, [key, value]) => [
                ...r,
                ...getPath(value).map(([path, value]) => [key + (path && '.') + path, value])
            ], [])
        : [['', value]],
    myObject = { name: 'Dan', age: 31, interests: ['coding', 'asking questions'], needsHelp: true, nestedData: { level1Data: { randomNumber: 41, anObject: { description: 'Nested data' } } } };

console.log(getPath(myObject));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 谢谢妮娜。这是一个非常有用的答案。如果可能的话,您能否在代码中发表评论,让我了解正在发生的事情?我觉得这将有助于我获得更多的理解并能够进一步扩展它。
猜你喜欢
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
  • 2013-03-26
  • 1970-01-01
相关资源
最近更新 更多