javascript - 如何递归嵌套对象值以使父对象包含相应的命名集合?

标签 javascript object recursion

好吧,首先:如果我能以一种不那么尴尬迟钝的方式表达我的问题,我就会这样做。 😜

我正在努力思考如何描述我正在尝试做的事情。

目标

我正在尝试迭代一个对象(具体来说,默认 TailwindCss 配置中的 colors 对象),以生成可以拉入 nunjucks 模板的标记列表。事实证明,这比我预想的更具挑战性。

我可能错过了一些基本的东西,但我不知道我不知道什么,你知道吗?

我有以下函数,它只循环颜色对象:

const tailwindSrc = require("../node_modules/tailwindcss/defaultConfig.js");
const colors = tailwindSrc.theme.colors;

const iterateObject = function (object) {
    let tokenList = [];
    Object.keys(object).forEach((key) => {
        Object.keys(object[key]).forEach((subkey) => {
            tokenList.push({
                token: {
                collectionKey: key,
                key: subkey,
                value: object[key][subkey],
                },
            });
        });
    });
    return tokenList;
  };

  iterateObject(colors);

这是我当前结果的代表性部分👇

{ token: { collectionKey: 'gray', key: '50',  value: '#f9fafb' } },
{ token: { collectionKey: 'gray', key: '100', value: '#f3f4f6' } },
{ token: { collectionKey: 'gray', key: '200', value: '#e5e7eb' } },
{ token: { collectionKey: 'gray', key: '300', value: '#d1d5db' } },
{ token: { collectionKey: 'gray', key: '400', value: '#9ca3af' } },
{ token: { collectionKey: 'gray', key: '500', value: '#6b7280' } },
{ token: { collectionKey: 'gray', key: '600', value: '#4b5563' } },
{ token: { collectionKey: 'gray', key: '700', value: '#374151' } },
{ token: { collectionKey: 'gray', key: '800', value: '#1f2937' } },
{ token: { collectionKey: 'gray', key: '900', value: '#111827' } }

但我希望灰色“集合”有一个值,该值本身就是一个包含其他两个名称-值对的对象。

有些东西,我猜是这样的。我根本不关心下面的结构;只是想或多或少地说明我需要如何对事物进行分组。

{
  token: { 
      collectionKey: 'gray',
      collectionEntries: {
          item: { key: '100', value: '#f3f4f6' }
          item: { key: '200', value: '#e5e7eb' }
          item: { key: '300', value: '#d1d5db' }
          item: { key: '400', value: '#9ca3af' }
          item: { key: '500', value: '#6b7280' }
          item: { key: '600', value: '#4b5563' }
          item: { key: '700', value: '#374151' }
          item: { key: '800', value: '#1f2937' }
          item: { key: '900', value: '#111827' }
      }
  }
}

在过去的两天里,我大概做了 8-10 次尝试来完成我所追求的目标。到目前为止还没有骰子。

在我看来,我的递归不够深入,无法完成我想要的事情,但当我尝试更深入时,我无法以一致、可重复的方式使事情顺利进行。我向 lodash 寻求帮助,它 mock 我。我什至尝试创建两个包含我需要的内容的对象,然后将它们合并在一起(la this )。没有骰子。

所以,我现在转向你,亲爱的读者。

当然,如果有一个完整的解决方案就太好了。但我也很乐意接受链接、建议、警告、观察等。欢迎任何帮助。

谢谢!


更新

感谢您的帮助,阿米尔!

您上面提供的内容看起来很有希望。虽然还没有完全实现,但我认为这是朝着正确方向迈出的一步。

这是我从您的代码中得到的结果:

[
  {
    collectionKey: 'pink',
    collectionEntries: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object]
    ]
  },
...
]

我应该注意到,该系列中的每个 collectionKey 都是'pink'。 😁

查看对象数组的数组。嗯。

我还应该注意到,我更改了您的一行代码

let token: {};

let token = {};

知道上面出了什么问题吗?

再次感谢!


更新#2

阿米尔,您要求查看我正在使用的数据的结构。我通过直接导入 colors 文件(而不是整个 tailwind 配置)来简化事情(我希望如此)。

这里是:

module.exports = {
  black: '#000',
  white: '#fff',
  rose: {
    50: '#fff1f2',
    100: '#ffe4e6',
    200: '#fecdd3',
    300: '#fda4af',
    400: '#fb7185',
    500: '#f43f5e',
    600: '#e11d48',
    700: '#be123c',
    800: '#9f1239',
    900: '#881337',
  },
  pink: {
    50: '#fdf2f8',
    100: '#fce7f3',
    200: '#fbcfe8',
    300: '#f9a8d4',
    400: '#f472b6',
    500: '#ec4899',
    600: '#db2777',
    700: '#be185d',
    800: '#9d174d',
    900: '#831843',
  },

  ...

};

请注意,某些条目不是嵌套的(例如 blackwhite),但其余条目是嵌套的。

如果能够适应这种差异就太好了。已尝试在 if 语句中包装两种不同的 .push 方法,但似乎当我修复一个用例时,我会破坏另一个用例。

再次感谢您的帮助!

最佳答案

现在我们有了您的输入格式,我们可以相当简单地对其进行转换。

这是一种技术,假设像 transparentblack 这样的条目应该尽可能像其他条目一样返回输出,并进一步假设 collectionEntries 应该是一个数组。 (您的格式不起作用,在您的对象中一遍又一遍地重复关键item。)

const collectColors = (colors) => Object .entries (colors)
  .map (([k, v]) => (
    Object (v) === v
      ? {token: { 
          collectionKey: k,
          collectionEntries: Object .entries (v) .map (([key, value]) => ({item: {key, value}}))
        }} 
      : {token: {collectionKey: k, collectionEntries: []}}
  ))

const colors = {transparent: "transparent", current: "currentColor", black: "#000", white: "#fff", gray: {50: "#f9fafb", 100: "#f3f4f6", 200: "#e5e7eb", 300: "#d1d5db", 400: "#9ca3af", 500: "#6b7280", 600: "#4b5563", 700: "#374151", 800: "#1f2937", 900: "#111827"}, red: {50: "#fef2f2", 100: "#fee2e2", 200: "#fecaca", 300: "#fca5a5", 400: "#f87171", 500: "#ef4444", 600: "#dc2626", 700: "#b91c1c", 800: "#991b1b", 900: "#7f1d1d"}, yellow: {50: "#fffbeb", 100: "#fef3c7", 200: "#fde68a", 300: "#fcd34d", 400: "#fbbf24", 500: "#f59e0b", 600: "#d97706", 700: "#b45309", 800: "#92400e", 900: "#78350f"}, green: {50: "#ecfdf5", 100: "#d1fae5", 200: "#a7f3d0", 300: "#6ee7b7", 400: "#34d399", 500: "#10b981", 600: "#059669", 700: "#047857", 800: "#065f46", 900: "#064e3b"}, blue: {50: "#eff6ff", 100: "#dbeafe", 200: "#bfdbfe", 300: "#93c5fd", 400: "#60a5fa", 500: "#3b82f6", 600: "#2563eb", 700: "#1d4ed8", 800: "#1e40af", 900: "#1e3a8a"}, indigo: {50: "#eef2ff", 100: "#e0e7ff", 200: "#c7d2fe", 300: "#a5b4fc", 400: "#818cf8", 500: "#6366f1", 600: "#4f46e5", 700: "#4338ca", 800: "#3730a3", 900: "#312e81"}, purple: {50: "#f5f3ff", 100: "#ede9fe", 200: "#ddd6fe", 300: "#c4b5fd", 400: "#a78bfa", 500: "#8b5cf6", 600: "#7c3aed", 700: "#6d28d9", 800: "#5b21b6", 900: "#4c1d95"}, pink: {50: "#fdf2f8", 100: "#fce7f3", 200: "#fbcfe8", 300: "#f9a8d4", 400: "#f472b6", 500: "#ec4899", 600: "#db2777", 700: "#be185d", 800: "#9d174d", 900: "#831843"}}

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

制作变体很容易。如果您只想跳过像 transparent 这样的内容,那么您可以使用以下变体:

const collectColors = (colors) => Object .entries (colors)
  .filter (([_, v]) => Object (v) === v)
  .map (([k, v]) => ({
    token: { 
      collectionKey: k,
      collectionEntries: Object .entries (v) .map (([key, value]) => ({item: {key, value}}))
    }
  }))

或者,如果您希望collectionEntries成为一个包含key-value对象的数组(额外的items有什么用 包装器?),您可以将相关行替换为

            collectionEntries: Object .entries (v) .map (([key, value]) => ({key, value}))

等等。

关于javascript - 如何递归嵌套对象值以使父对象包含相应的命名集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65430100/

相关文章:

javascript - 迭代 "subobjects"的 javascript 对象属性

javascript - 如何在react js中渲染对象内部的嵌套对象

php - 我需要一个 array_keys_recursive()

python - For 循环停止在递归函数中迭代

javascript - 单击链接时将颜色更改为#fff

javascript - 使用 Chrome 扩展修改协议(protocol)?

javascript - 让 UI 优先

javascript - bgSlider.js 需要激活幻灯片

ios - 从对象创建循环转换为在对象创建之间等待的 runBlock

javascript - 递归函数导致其他调用多次触发