cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
Sorting Lists
Problem

You have data in one or more lists or matrix vectors that you need to sort.

Solution

Use Sort List() or Sort List Into(), Rank(), or put the lists and vectors in a data table and sort it.

 

// Sort List example (makes new list)
names = {"fred", "Andy", "Rory", "bess", "susy", "perl"};
sname = Sort List( names );
Show( names, sname );

names = {"fred", "Andy", "Rory", "bess", "susy", "perl"}; // unchanged

sname = {"Andy", "bess", "fred", "perl", "Rory", "susy"}; // sorted
// Sort List Into example (in-place sort)
names = {"fred", "Andy", "Rory", "bess", "susy", "perl"};
Sort List Into( names );
Show( names );
names = {"Andy", "bess", "fred", "perl", "Rory", "susy"}; // sorted in-place
Both examples above operate on a single list. If there is a second list of phone numbers, they don't stick to the names.
To make several lists all have the same sort, you might use the Rank() function. The lists should have the same number of elements and no missing values in the sort-key list.
names = {"fred", "Andy", "Rory", "bess", "susy", "perl"};
phone = {"x321", "x322", "x323", "x324", "x325", "x326"};
rooms = {"1003", "1001", "1005", "1002", "1006", "1004"};

rnk = Rank( names ); // [2, 4, 1, 6, 3, 5]

// use the rnk vector to make sorted lists from the old lists
snames = names[rnk];
sphone = phone[rnk];
srooms = rooms[rnk];

Show( snames, sphone, srooms );
snames = {"Andy", "bess", "fred", "perl", "Rory", "susy"};
sphone = {"x322", "x324", "x321", "x326", "x323", "x325"};
srooms = {"1001", "1002", "1003", "1004", "1005", "1006"};
 
Above, the new lists with the prefix s are all sorted by name.
 
If you have multiple lists, of the same length, but paired across the lists, perhaps a data table would be a better data structure. You might find it easier to use a table because you can see it, save it, subset it, ...  But if you have the lists already, you can build a table from them. Here is a re-usable user function that does that:
// the zip function, named after a Python function that, like a zipper, zips two lists together
zip = Function( {variableNameList}, // a list of variable names
	{iVarName, dt, data}, // local variables
	dt = New Table( "zip", "invisible" ); // a hidden table, returned at end of this function
	For( iVarName = 1, iVarName <= N Items( variableNameList ), iVarName += 1,
		data = Eval( variableNameList[iVarName] ); // makes a copy of the data from the name
		If( Is Matrix( data ) | Is Number( data[1] ), // handle lists of numbers same as a matrix
			dt << New Column( Char( variableNameList[iVarName] ), "numeric", values( data ),
				setProperty( "wasMatrix", eval(Is Matrix( data ) ) ) ) // remember how to convert back, could be list
		, // else a list of strings
			dt << New Column( Char( variableNameList[iVarName] ), "character", values( data ),
				setProperty( "wasString", eval( Is String( data[1] ) ) ) ) // remember how to convert back, could be names
		);
	);
	dt << New Column( "_original order_", values( 1 :: N Rows( dt ) ) ); // this extra column is not required, but might be useful
	dt << setdirty( 0 ); // not required but avoids a "save?" prompt
	dt; // return
);
example:
cars = {chevy, volkswagon, honda, ford, toyota}; // list of unquoted names
doors = [4, 2, 2, 5, 2]; // matrix of numbers
miles = {30000, 20000, 40000, 10000, 50000}; // list of numbers
owner = {"fred", "susan", "ralph", "penelope", "terry"}; // list of quoted strings

zippedDt = zip( {cars, doors, miles, owner} );
zippedDt << sort( by( miles ), replacetable( 1 ) );

zippedDt << show Window; // table hidden by default
Lists are in table's columns, sorted by milesLists are in table's columns, sorted by miles
If you are working with lists, you might want all the lists back again. Here's an unzip function:
// unzip, similar to Python's unzip
unzip = Function( {dt}, // data table previously returned from zip (above)
	{result, cols, iCol, col, names, iRow}, // local variables
	cols = dt << getcolumnnames; // below, the _original order_ col gets skipped
	result = {}; // assemble all of the lists and matrices here, return at bottom
	For( iCol = 1, iCol < N Items( cols )/*skip last one*/, iCol += 1,
		col = Column( dt, cols[icol] ); // the Ith col in the table
		If( col << getdatatype( "English" ) == "Numeric", //
			// return the same type of object, list or matrix, supplied originally
			If( col << getproperty( "wasMatrix" ), // by checking the property we set above
				Insert Into( result, col << getValues ); // append a matrix
			, // else append a list of numbers
				result[N Items( result ) + 1] = As List( dt[0, iCol] )
			)
		, // else character column
			// return same type, list of names or list of strings...
			If( col << getproperty( "wasString" ), // check character col prop set above
				result[N Items( result ) + 1] = (dt[0, iCol]) // list of strings
			, // else turn the strings into names again
				result[N Items( result ) + 1] = As Name( dt[0, iCol] ) // list of names
			)
		);
	);
	result; // return
);
example:
{cars, doors, miles, owner} = unzip( zippedDt );

List( 4 elements ) assigned.

cars:{ford, volkswagon, chevy, honda, toyota}
doors:[5, 2, 4, 2, 2]
miles:{10000, 20000, 30000, 40000, 50000}
owner:{"penelope", "susan", "fred", "ralph", "terry"}

Finally
// Important! delete the invisible table!
Close( zippedDt, nosave );
Discussion

Be sure to clean up the invisible table if you use the zip/unzip functions. (They are unrelated to the compression function for .zip files. JMP has support for that in the zip archive object.)

The data table is a great tool for complicated data structures. You can make hidden or private tables for managing data without using the wrapper functions above. Lists may be more efficient than data tables if you need to add and remove a lot of items (queues and stacks might be slow if implemented as adding and removing rows from a table.) The zip function (above) expects a list of names. A name (no quotation marks) is not the same as a string (uses quotation marks). Passing a list of names reduces the number of times data is copied. 


See Also

https://www.jmp.com/support/help/14-2/list-functions.shtml 

JSL Cookbook

If you’re looking for a code snippet or design pattern that performs a common task for your JSL project, the JSL Cookbook is for you.

This knowledge base contains building blocks of JSL code that you can use to reduce the amount of coding you have to do yourself.

It's also a great place to learn from the experts how to use JSL in new ways, with best practices.