Object 如何将ramda食谱中的Flattobj函数转换为迭代函数

Object 如何将ramda食谱中的Flattobj函数转换为迭代函数,object,recursion,flatten,ramda.js,Object,Recursion,Flatten,Ramda.js,我正在处理一个测试环境nodejs/sequelize/mocha/chai。 我觉得这非常有用 测试对象时,例如由sequelize生成。 它使这些结构更容易被chai消化,结果更简洁 可惜它是以递归方式实现的:(.特别是在Javascript中,这意味着末日,因为总是有一个调用堆栈限制潜伏着。 像在setTimeout中包装递归函数这样的黑客似乎不适合我,而且有点难看。 我目前正试图以迭代的方式重写它,但至少对我来说,这是一个相当棘手的问题。 在ramda函数中处理while循环感觉不太好。

我正在处理一个测试环境nodejs/sequelize/mocha/chai。 我觉得这非常有用 测试对象时,例如由sequelize生成。
它使这些结构更容易被chai消化,结果更简洁
可惜它是以递归方式实现的:(.
特别是在Javascript中,这意味着末日,因为总是有一个调用堆栈限制潜伏着。
像在setTimeout中包装递归函数这样的黑客似乎不适合我,而且有点难看。
我目前正试图以迭代的方式重写它,但至少对我来说,这是一个相当棘手的问题。
在ramda函数中处理while循环感觉不太好。
有没有一种方法可以在不违反ramda惯例的情况下以调用堆栈友好的方式执行此操作?

const go = obj_ => chain(([k, v]) => {
  if (type(v) === 'Object' || type(v) === 'Array') {
    return pipe( 
        tap(console.log),            
        map(([k_, v_]) => [`${k}.${k_}`, v_]) 
     )(go(v))
  } else {
    return [[k, v]]
  }
}, toPairs(obj_))

const flattenObj = obj => {
  return fromPairs(go(obj))
}

flattenObj({a:1, b:{c:3}, d:{e:{f:6}, g:[{h:8, i:9}, 0]}})

{
  "a": 1,
  "b.c": 3,
  "d.e.f": 6,
  "d.g.0.h": 8,
  "d.g.0.i": 9,
  "d.g.1": 0
}
这与预期的一样,但当对象变得太复杂时,由于递归go函数,它会发生故障,导致调用堆栈超出错误。

如果它也适用于更复杂的结构,这将非常有用。

我不认为以递归方式实现它是一件坏事。这是处理递归数据结构(如JS对象)的最佳方式

但是,如果您想管理自己的堆栈,则始终可以将递归解决方案转换为迭代解决方案

const flattobj=(obj)=>{
常量结果=[];
常量步骤=对象条目(obj)
while(步长、长度){
常数[key,val]=步数。拼接(0,1)[0]
if(typeof val=='object'){
Array.prototype.push.apply(步骤、对象、条目(val).map(
([k,v])=>[key+'.+k,v]
))
}否则{
结果。推送([键,val])
}
}
返回结果.reduce((a[k,v])=>({…a[k]:v}),{})
}
const foo={a:1,b:{c:3},d:{e:{f:6},g:[{h:8,i:9},0]}

console.log(flattobj(foo))
非常感谢您的回答。当我深入研究我的问题时,我意识到用JSON.stringify(obj,null,2)转储sequelize ORM数据结构在原始源代码附近没有。原始源代码实际上是一个无穷无尽的数据流。我还以为我在测试一个纯JSON转储,但我无法重现调用堆栈错误。与此同时,我找到了该模块,它远远领先于任何纯ramda版本。但我对如何反递归也有着广泛的兴趣fy是一个ramda函数。围绕无穷无尽的数据流编写测试用例是相当困难的!