cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Have your say in shaping JMP's future by participating in the new JMP Wish List Prioritization Survey
Choose Language Hide Translation Bar
jconte
Level II

How to make recursive function with associative array as parameter

I'm trying to parse a nested associative array in JMP 16 (extracted from a JSON). The basic structure of the JSON is as follows:

{
"groupOp": "&", "rules": [ {"column": "col1", "op": "==", "value": 1}, {
"groupOp": "|",
"rules": [
{"column": "col2", "op": "==", "value": 2}
{"column": "col3", "op": "==", "value": 3}
]
}
}

This would allow structured storage of the nested condition "col1 == 1 & (col2 == 2 | col3 == 3)", and others of arbitrary depth.

 

I wrote a recursive function to parse this structure, using the contains function to distinguish the base case from the recursive case. However, I'm running into a stack overflow error. Upon debugging I realized that while "rule" had the correct value, "obj" stayed the same on each recursive call.

 

parseFilter = Function( {obj},
	If (obj << contains("groupOp") & obj << contains("rules"),
		str = "(";
		For Each({rule}, obj["rules"],
			show(rule);
			Concat(str, Recurse(rule) || " " || groupOp || " ");
		);
		Concat(str, ")");
		Return(str);
	, // else
		Return(":" || obj["column"] || " " || obj["op"] || " " || data );
	);
);

 Is this to do with the For Each function, having an associative array as a parameter, or something else?

3 REPLIES 3
Craige_Hales
Super User

Re: How to make recursive function with associative array as parameter

Without studying too deep, the first change you probably need is to make str be local. Change

parseFilter = Function( {obj},

to

parseFilter = Function( {obj},{str},

It looks like another parameter list, but it is actually a list of variables that are local to the function, and to each recursive call of the function.

 

Craige
jconte
Level II

Re: How to make recursive function with associative array as parameter

Thanks for the tip. Still running into the same issue though.

Craige_Hales
Super User

Re: How to make recursive function with associative array as parameter

I think this might be what you are after. Untested code follows...

json =
"\[
{
  "groupOp": "&",
  "rules": [
    {"column": "col1", "op": "==", "value": 1},
    {
      "groupOp": "|",
      "rules": [
        {"column": "col2", "op": "==", "value": 2},
        {"column": "col3", "op": "==", "value": 3}
      ]
    }
    ]
}
	
]\";

parseFilter = Function( {obj},
	{str, first},
	If( obj << Contains( "groupOp" ) & obj << Contains( "rules" ),
		str = "(";
		first = 1;
		For Each( {rule}, obj["rules"],
			If( first,
				first = 0;
			,// else
				str ||= (" " || obj["groupOp"] || " ")
			);
			str ||= Recurse( rule );
		);
		str ||= ")";
		Return( str );
	, // else
		Return( ":" || obj["column"] || " " || obj["op"] || " " || Char( obj["value"] ) )
	)
);

Write( parsefilter( Parse JSON( json ) ) );

(:col1 == 1 & (:col2 == 2 | :col3 == 3))

 

 

Craige