cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
mostarr
Level IV

Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

I got advice largely from Looping through an Associative Array's elements on how to iterate through associative arrays. My understanding is that the iterator iterates over the keys, not the values, but that you can easily access the values gives that you have the array.

 

My code is below.

 

Names Default To Here(1);
dt1 = Open("file path" );
dt2 = Open("file path 2");
Summarize(dt1, IDs = by(:ID)); //this finds all the unique IDs in the data file, which we will need
//First, populate the temporary data structure--associative array--from the dt1 data file which we will then copy over to the dt2 data file.
For (i=1, i<=N Items(IDs), i++,
	ID = IDs[i];
	temp_array = Associative Array ({"Val1","Val2","Val3"},{{},{},{}});
	For ( temp = temp_array << First, Is Empty(temp_array[temp]), temp = temp_array << Next(temp),//looping through temp_array's keys is clunky but done this way in JMP			
		query_date = dt1 << Select Where (:"ID" == ID);
		Write(query_date);
		
		//etc not there yet because the above not working
	);
);

 

The variable of interest at this point in my journey is query_date, which I need to proceed.  Problem is, as it is written, the inner loop doesn't run even once for some reason. The while condition in the loop should evaluate to True until I want the loop to terminate, so I have it set to 

Is Empty(temp_array[temp])

because  temp_array[temp] is the first value in the associative array, where temp is the first key, "Val1", and the value is {}. I guess an important question is: Does {} evaluate to True or False in Is Empty()? I can't even google this because {} are special characters which google doesn't process. So you can see why I'm confused.

 

I have the rest of my script coded out already, and I am fairly confident it will work with minor errors at this point, so if I can get past this hurdle that would help a lot. The pseudocode is very clear in my mind and, as a new JMP JSL user, things are becoming clearer, which I am grateful for. Thank you all for your help!

 

Mike

11 REPLIES 11
Craige_Hales
Super User

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

The for loop's condition needs to run while the key is not empty

For ( temp = temp_array << First, ! Is Empty(temp), temp = temp_array << Next(temp),

The associative array's <<first and <<next methods either return a key (a string or a number) or the special empty() value when there are no more keys. That key (if not empty) can be used as an index to the associative array.

The ! is the not operator.

 

edit: you might want something like this

temp_array = Associative Array( {"Val1", "Val2", "Val3"}, {{1, 2}, {}, {3, 4, 5}} );
For( temp = temp_array << First, !Is Empty( temp ), temp = temp_array << Next( temp ),
	If( N Items( temp_array[temp] ) > 0,
		Write( "\!nkey=", temp, " has ", N Items( temp_array[temp] ), " elements" ),
		Write( "\!nkey=", temp, " has no elements" )
	)
);

key=Val1 has 2 elements
key=Val2 has no elements
key=Val3 has 3 elements

Craige
mostarr
Level IV

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

Hi Craige. This seems to work. Thank you very much.

Michael

txnelson
Super User

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

I am not understanding why you are using an Associative Array?  Can you expand on what you envisioning the loop you are attempting to execute is supposed to do?

IsEmpty() is a function that returns a 1 if the script does not know what the referenced item is, and a 0 when the referenced item has been used in the script prior to the IsEmpty() execution.

Therefore:

a={};
isEmpty(s);
// returns 0 since  a  has been referenced prior in the script
isEmpty(b);
// returns 1 since JMP has not seen the variable b before

Concerning 

query_date = dt1 << Select Where (:"ID" == ID);

The Select Where() performs an action, but does not return anything.  Therefore query_date has no value.  What Select Where() does, is to set the Selected Row State to "On" for all of the rows in the data table that meet the selection criteria.  If more than one row in the data table has the value of ID multiple rows will be selected.  Perhaps what you are looking for is the value of query date for the selected row.  You can get the row numbers of the selected rows

dt1 << select where( :ID == ID );
theRows = dt1 << get selected rows;

It returns a matrix of the row numbers, not a scaler.  Therefore, to get the query_date, you have to reference the subscript.

dt1 << select where( :ID == ID );
theRows = dt1 << get selected rows;
query_date = dt1:query_date[ theRows[1] ];

A simpler form, not requiring the selection step would be to use Get Rows Where().

query_date = dt1:query_date[ dt1 << get rows where( :ID == ID )[1] ];

I hope I am helping and not confusing.  Please continue asking your questions.  

 

Jim
mostarr
Level IV

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

Thank you, Jim. That was nice of you for the quick response. I appreciate it. Give me a bit of time to parse all of this again, it's the weekend.

Mike
mostarr
Level IV

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

Thanks for the reply, Jim. One thing: I do not understand

query_date = dt1:query_date[ theRows[1] ];

as query_date is not yet instantiated.

Is this a typo (supposed to be a different variable)?

The Log also throws an error here: 

Scoped data table access requires a data table column or variable in access or evaluation of 'dt_ld4:query_date' , dt_ld4:query_date/*###*/

I would normally figure this out on my own but this problem is proving surprisingly challenging so I'm not entirely sure.

 

Thanks a bunch,

Mike

txnelson
Super User

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

OK......I was guessing.  You indicated that you needed to find the query_date, and it appeared that it had to do with your Select Where().  So I guessed that in your data table, there is a column called query_date, and the Select Where() or Get Rows Where(), would return the row that has the desired query date.  And apparently I guessed wrong as to where the query date can be found.

Jim
mostarr
Level IV

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

I'm running

dt1 << select where( :ID == ID );
theRows = dt1 << get selected rows;
Write(theRows);

just to check if selecting theRows is working, and it doesn't look like we're even getting that far, though. It prints:

[](0, 1)

where it should be printing a very comprehensive row (upward of 20 columns) from the data table for each iteration through the loop. I have no idea what is going on.

 

To try to help answer your implicit question, theRows is just a temporary variable to find the rows that result from the ID column value matching the value specified in the loop (there may be multiple rows of this nature due to multiple copies of ID).

 

I realize this is confusing... but that's sort of why I'm struggling, too.

 

Thanks in advance,

Mike

txnelson
Super User

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

can you provide a sample data table?
Jim
pmroz
Super User

Re: Iterating through an Associative Array Using a For Loop with an Empty While Condition Not Working

You will get the scoping error message if your variable and column name are the same.  For example you have a column and a variable named ID.  Also query_date.

 

Keep your column names (easier), and change your variable names.  E.g. :ID and one_id, :query_date and one_query_date.