将对象展平为相对字符串

时间:2018-05-22 21:37:39

标签: node.js recursion

我有一个对象例如:

{
    test: {
        a1: {
            b1: "someText"
        },
        a2:2,
    },
    test2:{  
        a3:3,
        a4:{
            "b4": "otherText",
            "b5": "textText"
        }
    }
}

我想迭代对象中的每个可能的键并创建一个新对象,其中键是一个相对路径,用下划线分隔,原始键和他的值。

例如:

{ 
  test_a1_b1: 'someText',
  test_a2: 2,
  test2_a3: 3,
  test2_a4_b4: 'otherText',
  test2_a4_b5: 'texttext' 
}

尝试了一些递归代码,但无法确定它。很高兴能得到你的帮助!

1 个答案:

答案 0 :(得分:1)

这是List monad的一个很好的用例,又名Array.prototype.flatMap(第3阶段)

以下deepEntriesObject.entries的工作方式类似;它返回一个[ key, value ]对的数组。

const deepEntries = (o = {}, path = []) =>
  Object (o) === o
    ? Object.entries (o)
        .flatMap
          (([ k, v ]) => deepEntries (v, [ ...path, k ]))
    : [ [ path, o ] ]

console.log (deepEntries (data))
// [ [ [ 'test', 'a1', 'b1' ], 'someText' ]
// , [ [ 'test', 'a2' ], 2 ]
// , [ [ 'test2', 'a3' ], 3 ]
// , [ [ 'test2', 'a4', 'b4' ], 'otherText' ]
// , [ [ 'test2', 'a4', 'b5' ], 'textText' ]
// ]

此结果优于您问题中的建议结果。如果由于某种原因你需要这种较小的形式,你可以很容易地得出它

deepEntries (data) .reduce
  ( (acc, [ keys, value ]) =>
      ({ ...acc, [keys .join ('_')]: value })
  , {}
  )
// { test_a1_b1: 'someText'
// , test_a2: 2
// , test2_a3: 3
// , test2_a4_b4: 'otherText'
// , test2_a4_b5: 'textText'
// }

如果您的环境中需要flatMap,则可以轻松填充

Array.prototype.flatMap = function (f)
{ return this .reduce
    ( (acc, x) =>
        acc .concat (f (x))
    , []
    )
}

在浏览器中运行以下程序以验证结果

Array.prototype.flatMap = function (f)
{ return this .reduce
    ( (acc, x) =>
        acc .concat (f (x))
    , []
    )
}

const deepEntries = (o = {}, path = []) =>
  Object (o) === o
    ? Object.entries (o)
        .flatMap
          (([ k, v ]) => deepEntries (v, [ ...path, k ]))
    : [ [ path, o ] ]

const data =
  { test:
      { a1: { b1: "someText" }
      , a2: 2
      }
  , test2 :
    { a3: 3
    , a4:
        { b4: "otherText"
        , b5: "textText"
        }
    }
  }

console.log (deepEntries (data))
// [ [ [ 'test', 'a1', 'b1' ], 'someText' ]
// , [ [ 'test', 'a2' ], 2 ]
// , [ [ 'test2', 'a3' ], 3 ]
// , [ [ 'test2', 'a4', 'b4' ], 'otherText' ]
// , [ [ 'test2', 'a4', 'b5' ], 'textText' ]
// ]

const lesserResult = 
  deepEntries (data) .reduce
    ( (acc, [ keys, value ]) =>
        ({ ...acc, [keys .join ('_')]: value })
    , {}
    )
console.log (lesserResult)
// { test_a1_b1: 'someText'
// , test_a2: 2
// , test2_a3: 3
// , test2_a4_b4: 'otherText'
// , test2_a4_b5: 'textText'
// }