使用Java的递归方法 [英] Recursive methods using Javascript

查看:116
本文介绍了使用Java的递归方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试复制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) returns undefined
  • 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?"

  • 这不仅适用于数组类型-我们可以将字符串,数字,数组,对象,数字数组,对象数组,包含字符串数组的对象(甚至nullundefined)进行字符串化,等等继续–您有了主意
  • 我们的stringifyJSON对象的每种情况都像一个小程序,它告诉我们确切地编码每种类型(例如StringNumberArrayObject等)的方式
  • 不要大惊小怪的typeof类型检查–在检查了undefinednull案例之后,我们知道我们可以尝试读取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 nulls and undefineds, 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 (eg String, Number, Array, Object etc)
  • no whacked out typeof type checking – after we check for the undefined and null cases, we know we can try to read the constructor 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 like x > y.length etc
  • no use of obj[0] or obj[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 after push 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆