使用Java的递归方法 [英] Recursive methods using Javascript
问题描述
我正在尝试复制json stringify方法,而是使用递归.我已经能够通过很多测试用例,但是当涉及到嵌套数组时,我似乎遇到了问题.如果数组('[]')中有任何空数组,我会得到类似[,7,9]而不是[[],7,9]的信息.另外,如果我通过:
I'm trying to replicate the json stringify method but instead use recursion. I've been able to pass alot of test cases but when it comes to nested arrays I seem to be having issues. if there's any empty array inside an array ('[]'), i get something like [,7,9] instead of [[],7,9]. Also if I pass in:
stringifyJSON([[["test","mike",4,["jake"]],3,4]])
"[[test,mike,4,jake,3,4]]"
我以为我已经接近完成这项工作了,但是我可能必须重新开始.你们对我可以更改哪些内容以使它适用于嵌套示例有任何想法吗?这是我现在拥有的代码:
I thought I was close in getting this to work, but I might have to start over. Do you guys have any ideas on what I might be able to change to make this work for nested examples? Here's the code I have now:
var testarray = [9,[[],2,3]] //should return '[9,[[],2,3]]'
var count = 0
var stringifyJSON = function(obj,stack) {
var typecheck = typeof obj;
var resarray = stack;
if(resarray == null){ //does resarray exist? Is this the first time through?
var resarray = [];
}
if(typeof obj === "string"){ //Is obj a string?
return '"' + String(obj) + '"';
}
if((Array.isArray(obj)) && (obj.length > 0)){ //If not a string, is it an object?
for(var i = 0; i<obj.length;i++){
if(Array.isArray(obj[i])){
var arraytemp = []
stringifyJSON(arraytemp.push(obj[i]),resarray) // this is probably incorrect, this is how i handle a nested array situation
}
if(typeof obj[i] === 'number'){ //if the number is inside of the array, don't quote it
resarray.push(obj[i]);
}
else if(typecheck === 'object' && Array.isArray(obj[0])){
resarray.push('[' + obj[i] + ']');
}
else{
resarray.push('"' + obj[i] + '"');
}
obj.shift() //delete the first object in the array and get ready to recurse to get to the second object.
stringifyJSON(obj,resarray); //remember the new array when recursing by passing it into the next recursive instance
}
}
if(obj !== null && typeof obj === 'object'){ //is obj an object?
for(var key in obj){
stringifyJSON(resarray.push(key + '"' + ':' + obj[key]),resarray)
}
}
if(typeof obj === "number" || obj == null || obj === true || obj === false){ //special cases and if it's a number
return '' + obj + ''
}
if(typecheck === 'object'){ //a special case where you have an empty array that needs to be quoted.
return '['+resarray+']'
}
return '' + resarray.join('') + '';
};
//JSON values cannot be a function, a date, or undefined
推荐答案
你们对我可能要进行哪些更改以使此示例适用于嵌套示例有任何想法吗?
Do you guys have any ideas on what I might be able to change to make this work for nested examples?
当然可以,但是这将使您失去整个功能,所以我希望您不要介意.我将提供项目符号清单,说明为什么这种方法必不可少,而您的方法从一开始:(
Sure, but it's going to scrap you entire function, so I hope you don't mind. I'll provide a bullet-list of points why this approach is essential and yours is essentially flawed from the get-go :(
角落案件
此函数对非空数据的constructor
属性进行简单的案例分析,并进行相应的编码.它可以处理很多您不太可能考虑的极端情况,例如
This function does a simple case analysis on a non-null data's constructor
property and encodes accordingly. It manages to cover a lot of corner cases that you're unlikely to consider, such as
-
JSON.stringify(undefined)
返回undefined
-
JSON.stringify(null)
返回'null'
-
JSON.stringify(true)
返回'true'
-
JSON.stringify([1,2,undefined,4])
返回'[1,2,null,4]'
-
JSON.stringify({a: undefined, b: 2})
返回'{ "b": 2 }'
-
JSON.stringify({a: /foo/})
返回{ "a": {} }
JSON.stringify(undefined)
returnsundefined
JSON.stringify(null)
returns'null'
JSON.stringify(true)
returns'true'
JSON.stringify([1,2,undefined,4])
returns'[1,2,null,4]'
JSON.stringify({a: undefined, b: 2})
returns'{ "b": 2 }'
JSON.stringify({a: /foo/})
returns{ "a": {} }
因此,要验证我们的stringifyJSON
函数是否正常运行,我将不直接对其进行测试.相反,我将编写一个test
方法,以确保我们编码的JSON的JSON.parse
实际上返回我们的原始输入值
So to verify that our stringifyJSON
function actually works properly, I'm not going to test the output of it directly. Instead, I'm going to write a little test
method that ensures the JSON.parse
of our encoded JSON actually returns our original input value
// we really only care that JSON.parse can work with our result
// the output value should match the input value
// if it doesn't, we did something wrong in our stringifier
const test = data => {
return console.log(JSON.parse(stringifyJSON(data)))
}
test([1,2,3]) // should return [1,2,3]
test({a:[1,2,3]}) // should return {a:[1,2,3]}
免责声明:很明显,我要分享的代码不是不能用作
JSON.stringify
的实际替代 –有无数的角落我们可能没有解决的情况.取而代之的是,共享此代码以演示如何执行此任务.可以在此功能中轻松添加其他极端情况.
Disclaimer: it should be obvious that the code I'm about to share is not meant to be used as an actual replacement for
JSON.stringify
– there's countless corner cases we probably didn't address. Instead, this code is shared to provide a demonstration for how we could go about such a task. Additional corner cases could easily be added to this function.
可运行的演示
事不宜迟,这是一个可运行的演示中的stringifyJSON
,该演示验证了几种常见情况的出色兼容性
Without further ado, here is stringifyJSON
in a runnable demo that verifies excellent compatibility for several common cases
const stringifyJSON = data => {
if (data === undefined)
return undefined
else if (data === null)
return 'null'
else if (data.constructor === String)
return '"' + data.replace(/"/g, '\\"') + '"'
else if (data.constructor === Number)
return String(data)
else if (data.constructor === Boolean)
return data ? 'true' : 'false'
else if (data.constructor === Array)
return '[ ' + data.reduce((acc, v) => {
if (v === undefined)
return [...acc, 'null']
else
return [...acc, stringifyJSON(v)]
}, []).join(', ') + ' ]'
else if (data.constructor === Object)
return '{ ' + Object.keys(data).reduce((acc, k) => {
if (data[k] === undefined)
return acc
else
return [...acc, stringifyJSON(k) + ':' + stringifyJSON(data[k])]
}, []).join(', ') + ' }'
else
return '{}'
}
// round-trip test and log to console
const test = data => {
return console.log(JSON.parse(stringifyJSON(data)))
}
test(null) // null
test('he said "hello"') // 'he said "hello"'
test(5) // 5
test([1,2,true,false]) // [ 1, 2, true, false ]
test({a:1, b:2}) // { a: 1, b: 2 }
test([{a:1},{b:2},{c:3}]) // [ { a: 1 }, { b: 2 }, { c: 3 } ]
test({a:[1,2,3], c:[4,5,6]}) // { a: [ 1, 2, 3 ], c: [ 4, 5, 6 ] }
test({a:undefined, b:2}) // { b: 2 }
test([[["test","mike",4,["jake"]],3,4]]) // [ [ [ 'test', 'mike', 4, [ 'jake' ] ], 3, 4 ] ]
那为什么更好?"
"So why is this better?"
- 这不仅适用于数组类型-我们可以将字符串,数字,数组,对象,数字数组,对象数组,包含字符串数组的对象(甚至
null
和undefined
)进行字符串化,等等继续–您有了主意 - 我们的
stringifyJSON
对象的每种情况都像一个小程序,它告诉我们确切地编码每种类型(例如String
,Number
,Array
,Object
等)的方式 - 不要大惊小怪的
typeof
类型检查–在检查了undefined
和null
案例之后,我们知道我们可以尝试读取constructor
属性. - 无需手动循环,我们就可以在精神上跟踪计数器变量,如何/何时增加它们
- 使用
&&
,||
,!
或检查诸如x > y.length
等的复杂的if
条件 - 不使用会压迫我们大脑的
obj[0]
或obj[i]
- 没有关于数组/对象为空的假设–并且无需必须检查
length
属性 - 没有其他的变化–这意味着我们不必考虑某些主返回值
resarray
或在程序的各个阶段发生push
调用后它处于什么状态
- this works for more than just Array types – we can stringify Strings, Numbers, Arrays, Objects, Array of Numbers, Arrays of Objects, Objects containing Arrays of Strings, even
null
s andundefined
s, and so on – you get the idea - each case of our
stringifyJSON
object is like a little program that tells us exactly how to encode each type (egString
,Number
,Array
,Object
etc) - no whacked out
typeof
type checking – after we check for theundefined
andnull
cases, we know we can try to read theconstructor
property. - no manual looping where we have to mentally keep track of counter variables, how/when to increment them
- no complex
if
conditions using&&
,||
,!
, or checking things likex > y.length
etc - no use of
obj[0]
orobj[i]
that stresses our brain out - no assumptions about Arrays/Objects being empty – and without having to check the
length
property - no other mutations for that matter – that means we don't have to think about some master return value
resarray
or what state it's in afterpush
calls happen at various stages in the program
自定义对象
JSON.stringify
允许我们在自定义对象上设置toJSON
属性,以便在对它们进行字符串化时获得所需的结果.
JSON.stringify
allows us to set a toJSON
property on our custom objects so that when we stringify them, we will get the result we want.
const Foo = x => ({
toJSON: () => ({ type: 'Foo', value: x })
})
console.log(JSON.stringify(Foo(5)))
// {"type":"Foo","value":5}
我们可以轻松地在上面的代码中添加这种功能-粗体
We could easily add this kind of functionality to our code above – changes in bold
const stringifyJSON = data => {
if (data === undefined)
return undefined
else if (data === null)
return 'null'
else if (data.toJSON instanceof Function)
return stringifyJSON(data.toJSON())
...
else
return '{}'
}
test({toJSON: () => ({a:1, b:2})}) // { a: 1, b: 2 }
这篇关于使用Java的递归方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!