Vision Tutorial 4: Using Lists
Reminder! To run these examples, you should first start a new session then load the sample database using:"/localvision/samples/general/sample.load" asFileContents evaluate ;Any other files referenced can be read from the /localvision/samples/general/ directory.Note: The sample.load file runs by default on a Unix environment. If you are using a Windows NT platform, this location may be prefixed by a drive and optional path (e.g. d:/visiondb/localvision/samples/general/sample.load). Check with your Vision Administrator for further details.
List Creation and Basic Access
Vision allows you to store one or more objects in a list. To create a list, just separate the objects you wish to include in the list with commas. For example, assume you wish to create a list containing the companies GM, IBM, and Exxon and name this list testList. Type and execute the following:
!testList <- Named Company GM, Named Company IBM, Named Company XONYou should see:
List of 3Vision has executed your request and created a variable called testList. The output aList informs you that you have created a list of elements. If you wish to suppress the printing of aList, simply type ; at the end of the previous expression. Notice that the expression Named Company is repeated for each element in the list. The send: message can be used to streamline this operation. Type the following:
!testList <- Named Company send: [ GM, IBM, XON ]The two previous examples produce identical results.
The count message can be sent to a list of elements to return the number of elements in the list. For example, the expression:
testList countreturns the number 3, the total number of companies in testList.
To access the list of all instances in the class Company, execute the expression:
!fullList <- Company masterList ;Vision has executed your request and created a variable called fullList. The expression:
fullList countreturns the number 38, the total number of companies in fullList.
The asList message can be used to produce a 1 element list from a single object. For example:
!gmAsList <- Named Company GM asList ;produces a list object that contains 1 object, the company GM. You can append additional objects to gmAsList and use all the other List messages with this list.
Individual objects in a List can be accessed directly using the at: message. For example, the expression:
testList at: 2returns the second element of this list. In this case, the Company object IBM is returned. The expression:
(testList at: 2) = Named Company IBMreturns the value TRUE.
The "do:" Message
Now that you know how many companies are in testList, you may wish to analyze and display information for each company in the list. The do: message is used for this purpose. You used this message in a previous section to display multiple pieces of information for a single company.
The syntax for the do: message is:
list do: [ operation 1 ; operation 2 ; operation 3 ; . . . operation n ; ] ;where list is a list of elements (e.g., testList) and each operation represents an action you want executed for each element in the list. As usual, each separate operation is followed by the ; character.
The expression:
testList do: [ ticker print; ] ;produces the output:
GMIBMXONThis program prints the ticker for each company in testList. However, the output in this example is almost unreadable. That is because you did not tell Vision to perform a carriage return after printing each ticker. Instead of using the print message, use printNL as shown below:
testList do: [ ticker printNL; ] ;The Output Window should display:
GM IBM XONThis program prints a ticker for each company in testList, followed by a carriage return.
The message do: operates like a loop that says print the ticker for company 1 in testList followed by a carriage return, print the ticker for company 2 in testList followed by a carriage return, and so on. If you wished to perform this same operation for a list containing 10,000 companies, only the list name would need to be changed. For example, you could use fullList to display the ticker for each company instance:
fullList do: [ ticker printNL; ] ;Suppose you wish to print the names of the companies in testList. The expression:
testList do: [ name printNL ] ;produces:
General Motors Corp IBM Corp Exxon CorpIn addition to name, print the sales for each company in testList. The expression:
testList do: [ name print; sales printNL; ] ;produces:
General Motors Corp 101781.00 IBM Corp 54217.02 Exxon Corp 76416.00To get the sales column to line up neatly, specify a column width for the name using the print: message as shown below:
testList do: [name print: 35; sales printNL; ] ;You should see:
General Motors Corp 101781.00 IBM Corp 54217.02 Exxon Corp 76416.00The message print: 35 reserves 35 spaces for each company's name and inserts spaces for names that have fewer characters.
The do: message can be used with calculations as well. Suppose you wish to calculate the price-earnings ratio for each company in testList. The expression:
testList do:[ name print: 35; sales print: 10 ; price / earningsPerShare printNL: 8 ; ] ;produces the results:
General Motors Corp 101781.00 6.39 IBM Corp 54217.02 9.26 Exxon Corp 76416.00 8.62In this case, the do: message executes three operations for each element in the list, printing the name, the sales value, and the price-earnings ratio followed by a carriage return. The sales values is printed in 10 character positions and the price-earnings ratio is printed in 8 positions. Change testList to fullList to execute this report for all the companies.
The "select:" Message<
It is often useful to restrict a list to objects that meet certain criteria. For example, you may wish to find the companies in fullList whose sales were greater than 15,000 and produce the previous report for these companies only. The expression:
fullList select: [ sales > 15000 ] . do: [ name print: 35 ; sales print: 10 ; price / earningsPerShare printNL: 8 ; ] ;produces:
Aetna Life & Cas 22114.11 5.46 American Tel & Tel 51209.02 23.20 Amoco Corp 20174.00 19.91 Atlantic Richfield 16282.00 18.15 Boeing Co 15355.00 26.63 ...This expression selects companies in fullList whose sales were greater than 15,000 and displays each company's name, sales, and price-earnings ratio for the companies that passed the criteria.
The select: message returns a list of those elements in the original list that meet the criteria specified. Pictorially the select: message works as follows:
The resultant list is a new list object that contains a subset of the objects in the original list. The resultant list can be empty (i.e., contain no objects) but will never have more elements than the original list. When you send the do: message to the resultant list, the report is only produced for those companies in this list. This same task could have been accomplished by creating a new variable that represents the result of screening for the specified criteria and then producing the report for this list as shown below:
!selectList <- fullList select: [ sales > 15000 ] ; selectList do: [ name print: 35 ; sales print: 10 ; price/earningsPerShare printNL: 8 ; ];This program produces results that are identical to the previous example.
If you wish to find the companies that had sales greater than 15,000 and a price-earnings ratio of less than 10, type the expression:
fullList select: [ sales > 15000 && (price / earningsPerShare) < 10 ] . do: [ name print:35; sales print: 10 ; price / earningsPerShare printNL: 8 ; ] ;You should see
Aetna Life & Cas 22114.11 5.46 CIGNA Corp 16909.30 6.90 Chrysler Corp 26276.51 3.92 Citicorp 27988.01 3.67 Ford Motor Company 71643.38 4.36 General Motors Corp 101781.00 6.39 IBM Corp 54217.02 9.26 Travelers Corp 17459.10 5.49The message && is the relational operator for and. It is used to create selection criteria where several criteria must all be TRUE. The message | | is the relational operator for or and is used to specify criteria where either or both criteria are TRUE. For example, if you wish to find the companies whose sales are greater than 15,000 or that have a price-earnings ratio of less than 15, execute:
fullList select: [ sales > 15000 || (price / earningsPerShare) < 10 ] . do: [ name print: 35 ; sales print: 10 ; price/ earningsPerShare printNL: 8 ; ];You should see:
Aetna Life & Cas 22114.11 5.46 American Tel & Tel 51209.02 23.20 Amoco Corp 20174.00 19.91 Atlantic Richfield 16282.00 18.15 Boeing Co 15355.00 26.63 ...Notice that calculations (e.g., price / earningsPerShare) can be performed within selection brackets. The selection criteria is really just a Vision program. Within the square brackets, you can define temporary variables, perform conditional tests, and do complex calculations to specify your criteria.
Sort Messages
It is often useful to display your information in sorted order. The sortDown: and sortUp: messages enable you to do this. For example, after you performed your screen on fullList, you may wish to display the results from highest to lowest sales. For example, the expression:
fullList select: [ sales > 15000 && (price / earningsPerShare) < 10 ] . sortDown: [ sales ] . do: [ name print: 35 ; sales print: 10 ; price / earningsPerShare printNL: 8 ; ] ;produces the output:
General Motors Corp 101781.00 6.39 Ford Motor Company 71643.38 4.36 IBM Corp 54217.02 9.26 Citicorp 27988.01 3.67 ...As with other list messages, you are not limited in the complexity of the calculation to be sorted on. For example you may sort on the price-earnings ratio by executing the following:
fullList select: [ sales > 15000 && (price / earningsPerShare) < 10 ] . sortUp: [ price / earningsPerShare ] . do: [ name print: 35 ; sales print: 10 ; price / earningsPerShare printNL: 8 ; ] ;producing the results:
Citicorp 27988.01 3.67 Chrysler Corp 26276.51 3.92 Ford Motor Company 71643.38 4.36 Aetna Life & Cas 22114.11 5.46 ...In this case, the sortUp: message was used to sort the values from lowest to highest price-earnings ratio. You can perform multiple sorts using the sortUpBy: then: message and supplying two criteria. For example, to sort by the integer portion of the price-earnings ratio then by name, use:
fullList select: [ sales > 15000 && (price / earningsPerShare) < 10 ] . sortUpBy: [ (price / earningsPerShare) asInteger ] then: [ name ] . do: [ name print: 35 ; sales print: 10 ; price / earningsPerShare printNL:8 ; ] ;
You should see:
Chrysler Corp 26276.51 3.92 Citicorp 27988.01 3.67 Ford Motor Company 71643.38 4.36 Aetna Life & Cas 22114.11 5.46 ...Notice that Chrysler now appears before Citicorp. Since the integer value of the ratio is 3 in both cases, the name sort is used as a secondary sort.
Additional variations of the Sort:messsages are available.
The "extendBy:"Message
The last example used the calculation price / earningsPerShare three times (selecting, sorting, and doing) thus creating two inefficiencies. First, it is tedious to type in the same calculation three times, particularly when calculations use many variables. In addition, by writing the calculation three times, you are asking Vision to retrieve the same information for the same companies three times. As usual, Vision provides a more efficient way to accomplish this.
The message extendBy: lets you calculate variables once for each element in the list and then lets you reuse this information. For example, the previous example can be more effectively written as follows:
fullList extendBy: [ !pe <- price / earningsPerShare; ] . select: [ sales > 15000 && pe < 10 ] . sortUpBy: [ pe ] then: [ name ] . do: [ name print: 35 ; sales print: 10 ; pe printNL: 8 ; ] ;This program produces the same output as the prior example. Instead of calculating price / earningsPerShare three times, the extendBy: message allows you to create a variable that stores the result of this calculation once.
All objects in the list respond to the pe message just like any other message. All objects in the list continue to respond to the messages already defined.
Pictorially the extendBy: message works as follows:
Within the square brackets, you can define as many variables as you would like. Each variable should be introduced with the symbol ! followed by a variable name. Each variable that you define can be thought of as a new column for the list. For example:
fullList extendBy: [ !pe <- price / earningsPerShare; !margin <- netIncome / sales; ] . select: [ sales > 15000 && pe < 10 ] . sortUp: [ pe ] . do:[ name print: 35 ; margin print ; sales print: 10 ; pe printNL: 8 ; ] ;produces:
Citicorp 0.04 27988.01 3.67 Chrysler Corp 0.05 26276.51 3.92 Ford Motor Company 0.06 71643.38 4.36 Aetna Life & Cas 0.04 22114.11 5.46 Travelers Corp 0.02 17459.10 5.49 General Motors Corp 0.03 101781.00 6.39 CIGNA Corp 0.04 16909.30 6.90 IBM Corp 0.10 54217.02 9.26The new variable definitions can be as simple or complex as needed. For example, you could create an additional variable that contains an * if margin is more than .9 or sales is less than 20,000 using:
fullList extendBy: [ !pe <- price / earningsPerShare; !margin <- netIncome / sales; !flag <- " " ; margin > .9 || sales < 20000 ifTrue:[ :flag <- "*"; ] ; ] . select: [ sales > 15000 && pe < 10 ] . sortUp: [ pe ] . do: [ flag print: 2 ; name print: 35 ; margin print ; sales print: 10 ; pe printNL: 8 ; ] ;producing the output:
Citicorp 0.04 27988.01 3.67 Chrysler Corp 0.05 26276.51 3.92 Ford Motor Company 0.06 71643.38 4.36 Aetna Life Cas 0.04 22114.11 5.46 * Travelers Corp 0.02 17459.10 5.49 General Motors Corp 0.03 101781.00 6.39 * CIGNA Corp 0.04 16909.30 6.90 IBM Corp 0.10 54217.02 9.26
List Rank, Decile, and Quintile Messages
You may wish to determine the rank of each company in a list based on one of its data values. In fullList, for example, the company with the highest sales would receive a rank of 1 and the one with the lowest sales would receive a rank of 38. Vision provides two messages, rankUp: and rankDown: for this purpose. The rankUp:message assigns the value 1 to the list element with the lowest value for the supplied criteria. The rankDown: message assigns the value 1 to the list element with the highest value for the supplied criteria.
When you send one of these messages to a list, Vision returns an extended variable for the list named rank. For example, if you wished to rank the companies selected in the previous examples from highest to lowest sales and sort the companies by pe, you could execute:
fullList extendBy: [ !pe <- price / earningsPerShare; !margin <- netIncome / sales; ] . select: [ sales > 15000 && pe < 10 ] . rankDown: [ sales ] . sortUp: [ pe ] . do: [ name print: 30 ; margin print ; sales print: 10 ; rank print ; pe printNL: 8 ; ] ;producing the output:
Citicorp 0.04 27988.01 4 3.67 Chrysler Corp 0.05 26276.51 5 3.92 Ford Motor Company 0.06 71643.38 2 4.36 Aetna Life & Cas 0.04 22114.11 6 5.46 Travelers Corp 0.02 17459.10 7 5.49 General Motors Corp 0.03 101781.00 1 6.39 CIGNA Corp 0.04 16909.30 8 6.90 IBM Corp 0.10 54217.02 3 9.26The displayed rank indicates the company's position in the list by sales. Citicorp, with a sales rank of 4, is displayed first because the report is sorted by pe and Citicorp has the lowest pe value. If you were to rank and sort the list by the same value, the companies will display in rank order. For example, to rank and sort the list by pe, type the following:
fullList extendBy: [ !pe <- price / earningsPerShare ; !margin <- netIncome / sales ; ] . select: [ sales > 15000 && pe < 10 ] . rankUp: [ pe ] . sortUp: [ pe ] . do: [ name print: 30 ; margin print ; sales print: 10 ; rank print ; pe printNL: 8 ; ] ;producing the output:
Citicorp 0.04 27988.01 1 3.67 Chrysler Corp 0.05 26276.51 2 3.92 Ford Motor Company 0.06 71643.38 3 4.36 Aetna Life & Cas 0.04 22114.11 4 5.46 Travelers Corp 0.02 17459.10 5 5.49 General Motors Corp 0.03 101781.00 6 6.39 CIGNA Corp 0.04 16909.30 7 6.90 IBM Corp 0.10 54217.02 8 9.26Notice that the ranks are in ascending order in this case.
In the last few examples, you have performed the same extendBy: and select: operations repeatedly. You may wish to create a new list that represents the original list containing only those companies meeting your criteria and providing the two pre-calculations. To do this, type:
!subset <- fullList extendBy: [ !pe <- price / earningsPerShare; !margin <- netIncome / sales; ]. select: [ sales > 15000 && pe < 10] ;The variable subset can now be used directly. For example, to generate the last report using this list type:
subset rankUp: [ pe ] . sortUp: [ pe ] . do: [ name print: 30 ; margin print; sales print: 10 ; rank print; pe printNL: 8 ; ] ;The output should be identical to the previous report. Notice that there was no need to do the extend: or select: operations this time.
The decileUp: and decileDown: messages have been implemented to assign a value from 1 to 10 to each element in the list based on the criteria supplied. The decileUp: message assigns the value 1 to the first 10% of the list elements with the lowest values, the value 2 to the next 10%, and so on with the value 10 assigned to the list elements in the top 10%. The decileDown: message assigns the value 1 to the first 10% of the list elements with the highest values and the value 10 to the list elements in the bottom 10%. When you send one of these messages to a list, Vision returns an extended variable for the list named decile. For example:
fullList decileDown: [ sales ] . do: [ name print: 30 ; sales print: 10 ; decile printNL ; ] ;produces the output:
Aetna Life & Cas 22114.11 4 American Tel & Tel 51209.02 2 Amoco Corp 20174.00 4 Atlantic Richfield 16282.00 6 ...Each company is assigned a decile value from 1 to 10 based on where its sales value falls compared to the other companies in the list. The companies with the largest sales all have the decile value 1. The companies with the smallest sales all have the decile value 10. Sorting the list by sales may make this clearer:
fullList decileDown: [ sales ] . sortDown: [ sales ] . do: [ name print: 30 ; sales print: 10 ; decile printNL ; ] ;You should see:
General Motors Corp 101781.00 1 Exxon Corp 76416.00 1 Ford Motor Company 71643.38 1 IBM Corp 54217.02 1 Mobil Corporation 51223.02 2 American Tel & Tel 51209.02 2 Sears Roebuck & Co 48439.61 2 General Electric Co 39315.01 2 DuPont EI de Nemours 30468.01 3 . . .The quintileUp: and quintileDown: messages are identical to the decile messages except they assign a value from 1 to 5, returned in a variable named quintile. For example, you could assign a sales quintile and an earningsPerShare decile value using the following:
fullList quintileDown: [ sales ] . decileUp: [ earningsPerShare ] . do: [ name print: 30 ; sales print: 10 ; quintile print ; earningsPerShare print ; decile printNL ; ] ;producing the output:
Aetna Life & Cas 22114.11 2 7.48 9 American Tel & Tel 51209.02 1 1.88 2 Amoco Corp 20174.00 2 2.65 4 Atlantic Richfield 16282.00 3 6.68 8 BellSouth Corp 12269.10 4 3.46 6 Boeing Co 15355.00 3 1.38 2 ...
The "groupedBy:" Message
The groupedBy: message provides you with a powerful tool for aggregation, enabling you to simultaneously analyze information at a detailed and aggregate level. The groupedBy: message is used to organize your original list into a list of sublists or groups based on criteria that you specify. You can then perform summary analysis on each group as well as analyze the individual elements in each group.
The groupedBy: message is often used to group information by industry, analyst, rating, or any other criteria that allows you to classify similar information.
To group the list subset by sector, and display each sector's name, type the following expression:
subset groupedBy: [ industry sector ] . do: [ name printNL; ] ;You should see:
Durables Finance TechnologyBy asking Vision to group subset by sector, Vision returns a list of the sectors that exist in subset. When you send the do: message to this list and ask for the name of each element to be printed, the sector names are displayed.
Your original list of companies is not lost. Each element in the list formed by the groupedBy: message responds to the message groupList. This message returns the list of companies from the original list that are associated with the specific group. To determine the number of companies in each sector, type the following:
subset groupedBy: [ industry sector ] . do: [ name print: 35 ; groupList count printNL; ] ;producing the output:
Durables 3 Finance 4 Technology 1To display the companies in each sector, and the sales, pe and margin for each company, type the following:
subset groupedBy: [ industry sector ] . do: [ name printNL; # print sector name groupList do: [ # for each company in sector " " print:5; # indent 5 spaces name print: 30 ; # print company data margin print ; sales print: 10 ; pe printNL; ] ; ];You should see:
Durables Chrysler Corp 0.05 26276.51 3.92 Ford Motor Company 0.06 71643.38 4.36 General Motors Corp 0.03 101781.00 6.39 Finance Aetna Life & Cas 0.04 22114.11 5.46 CIGNA Corp 0.04 16909.30 6.90 Citicorp 0.04 27988.01 3.67 Travelers Corp 0.02 17459.10 5.49 Technology IBM Corp 0.10 54217.02 9.26Pictorially the groupedBy: message works as follows:
Grouping introduces a concept known as nested lists. The outer list represents a list of sectors. Each element in this outer list in turn responds to the message groupList which returns the set of elements from the original list that are in the current group. Since this subset is itself a list, you can perform any list operations on it, including count, do:, and select:. For example, to sort the companies in each group by sales, use the following:
subset groupedBy: [ industry sector ] . do: [ name printNL ; # print sector name groupList sortDown: [ sales ] . # sort companies in sector do: [ # sort each company in sector do: [ " " print: 5 ; # indent 5 spaces name print: 30 ; # print company data margin print ; sales print: 10 ; pe printNL ; ] ; ] ;You should see:
Durables General Motors Corp 0.03 101781.00 6.39 Ford Motor Company 0.06 71643.38 4.36 Chrysler Corp 0.05 26276.51 3.92 Finance Citicorp 0.04 27988.01 3.67 Aetna Life & Cas 0.04 22114.11 5.46 Travelers Corp 0.02 17459.10 5.49 CIGNA Corp 0.04 16909.30 6.90 Technology IBM Corp 0.10 54217.02 9.26You can sort each of the group levels independently. For example, you could sort the sector groups by number of companies in the group using the following:
subset groupedBy: [ industry sector ] . sortUp: [ groupList count ] . # sort sectors by number in group do: [ name printNL ; # print sector name groupList sortDown: [ sales ] . # sort companies in sector do: [ # for each company in sector do: [ " " print: 5 ; # indent 5 spaces name print: 30 ; # print company data margin print ; sales print: 10 ; pe printNL; ] ; ] ;You should see:
Technology IBM Corp 0.10 54217.02 9.26 Durables General Motors Corp 0.03 101781.00 6.39 Ford Motor Company 0.06 71643.38 4.36 Chrysler Corp 0.05 26276.51 3.92 Finance Citicorp 0.04 27988.01 3.67 Aetna Life & Cas 0.04 22114.11 5.46 Travelers Corp 0.02 17459.10 5.49 CIGNA Corp 0.04 16909.30 6.90Since the groupList is a list, it can be grouped further, as shown below:
subset groupedBy: [ industry sector ] . # group by sector do: [ "SECTOR: " print; name printNL; # print sector's name groupList groupedBy: [ industry ] . # group companies in sector do: [ # by industry " INDUSTRY: " print; name printNL; # print industry's name groupList # for each company do: [ # in industry do: " " print: 8 ; # indent 8 spaces name print: 30 ; # print company data sales print:10 ; price print:10 ; earningsPerShare print: 10 ; newLine print ; ] ; # end of companies in ind. ] ; # end of industries in sector newLine print; # skip line between sectors ] ; # end of sectorsYou should see:
SECTOR: Durables INDUSTRY: Automotive Chrysler Corp 26276.51 23.13 5.90 Ford Motor Company 71643.38 39.50 9.05 General Motors Corp 101781.00 32.13 5.03 SECTOR: Finance INDUSTRY: Banks Citicorp 27988.01 15.63 4.26 INDUSTRY: Insurance Aetna Life & Cas 22114.11 40.88 7.48 CIGNA Corp 16909.30 50.00 7.25 Travelers Corp 17459.10 22.50 4.10 SECTOR: Technology INDUSTRY: Computers and Services IBM Corp 54217.02 80.75 8.72 ...This report organizes the list subset into sectors. Within each sector the industries are separated, and then the companies are listed under their corresponding industry. This example uses the groupedBy: message twice; once to group the original list into sectors; the second time to group the companies in a given sector into industries. You can change the initial list from subset to fullList, to display this report for all companies.
Statistical Messages
Vision offers various messages for calculating summary statistics about a list. For example, if you wish to calculate the average sales for the companies in fullList execute:
fullList average: [ sales ]You should see:
25701.95To determine the total sales in fullList execute:
fullList total: [ sales ]producing the output:
976674.02Other statistical messages include: average:, max:, median:, min:, mode:, stdDev:, and total:.
Many of these messages, such as median: were written in Vision and can be modified or expanded as needed. The brackets can contain a simple message, a calculation, or a complex program.
To save the total, average, minimum and maximum sales for the companies in fullList in the variables fullTot, fullAvg, fullMin, and fullMax respectively, execute:
!tot <- fullList total: [ sales ]; !avg <- fullList average: [ sales ]; !min <- fullList min: [ sales ]; !max <- fullList max: [ sales ];To print the results for each variable with a description execute:
"TOTAL SALES" print: 35 ; tot printNL ; "AVERAGE SALES" print: 35 ; avg printNL ; "MIN SALES" print: 35 ; min printNL ; "MAX SALES" print: 35 ; max printNL ;producing the output:
TOTAL SALES 976674.02 AVERAGE SALES 25701.95 MIN SALES 8090.00 MAX SALES 101781.00The following program adds subtotals to the sector report created earlier:
subset groupedBy: [ industry sector ] . do: [ printNL ; # print sector name groupList do: [ # for each company in sector do: [ " " print: 5 ; # indent 5 spaces name print: 30 ; # print company data sales printNL; ] ; "SUB TOTALS: " print: 35 ; groupList total: [ sales ] . printNL ; newLine print ; ] ;You should see:
Durables Chrysler Corp 26276.51 Ford Motor Company 71643.38 General Motors Corp 101781.00 SUB TOTALS: 199700.89 Finance Aetna Life & Cas 22114.11 CIGNA Corp 16909.30 Citicorp 27988.01 Travelers Corp 17459.10 SUB TOTALS: 84470.52 . . .To display subtotals for the industry-sector report, use:
fullList groupedBy: [ industry sector ] . do: [ "Sector: " print ; name printNL ; groupList groupedBy: [ industry ] . do: [" Industry: " print ; name printNL ; groupList do:[ " " print: 8 ; name print: 30 ; sales print: 10 ; price print: 10 ; earningsPerShare print: 10 ; newLine print ; ]; #-- Industry Sub Totals "Industry Totals: " print: 38 ; groupList total: [ sales ] . print: 10 ; " " print: 10 ; groupList average: [ earningsPerShare ] . print: 10 ; newLine print ; newLine print ; ]; #-- Sector Sub Totals "Sector Totals: " print: 38 ; groupList total: [ sales ] . print: 10 ; " " print: 10 ; groupList average: [ earningsPerShare ] . print: 10 ; newLine print ; newLine print ; ] ; # end of sectorsproducing the output:
Sector: Non-durables Industry: Food, Beverage, Tobacco Pepsico Inc 11485.20 37.88 0.77 Philip Morris Cos 22279.00 84.75 1.94 Industry Totals: 33764.20 1.35 Industry: Household Products Eastman Kodak Co 13305.00 44.50 3.52 Procter & Gamble Co 17000.00 49.38 0.47 Industy Totals: 30305.00 2.00 Sector Totals: 64069.20 1.68 Sector: Durables Industry: Automotive Chrysler Corp 26276.51 23.13 5.90 Ford Motor Company 71643.38 39.50 9.05 General Motors Corp 101781.00 32.13 5.03 Industry Totals: 19700.89 6.66 Sector Totals: 199700.89 6.66 ...
Other List Messages
Many applications require merging several lists together. Vision offers several messages to support these operations. Start by creating two lists: techList which contains the companies IBM, DEC, and HWP and highSalesList which includes companies with sales over 15,000.
!techList <- Named Company send: [ IBM, DEC, HWP ] ; !highSalesList <- fullList select: [ sales > 15000 ] ;First, determine the number of companies in each list:
techList countYou should see:
3Now type:
highSalesList countYou should see:
22Suppose you wish to create a new list which includes all of the companies in highSalesList and techList. The append: message can be used for this purpose. To define a new list called combinedList with all of the companies in both lists execute the following:
!combinedList <- highSalesList append: techList;Now count the number of companies in combinedList using:
combinedList countproducing the output:
25To print the names of the companies in combinedList type the following:
combinedList do: [ name printNL ] ;You should see:
Aetna Life & Cas American Tel & Tel Amoco Corp Atlantic Richfield Boeing Co CIGNA Corp Chevron Corp Chrysler Corp Citicorp DuPont EI de Nemours Exxon Corp Ford Motor Company GTE Corp General Electric Co General Motors Corp IBM Corp K Mart Corp Mobil Corporation Philip Morris Cos Procter & Gamble Co Sears Roebuck & Co Travelers Corp IBM Corp Digital Equipment Corp Hewlett-Packard CoNotice that IBM appears twice. The append: message does not remove duplicate companies. To eliminate the duplication, use the union: message. Union finds elements that are in either or both lists specified. Change the previous example to use union: instead of append: :
!combinedList <- highSalesList union: techList; combinedList do: [ name printNL; ];You should see the following:
Aetna Life & Cas American Tel & Tel Amoco Corp Atlantic Richfield Boeing Co CIGNA Corp Chevron Corp Chrysler Corp Citicorp Digital Equipment Corp DuPont EI de Nemours Exxon Corp Ford Motor Company GTE Corp General Electric Co General Motors Corp Hewlett-Packard Co IBM Corp K Mart Corp Mobil Corporation Philip Morris Cos Procter & Gamble Co Sears Roebuck & Co Travelers CorpNotice that this time, IBM appears only once.
Suppose you wish to create a list of all companies excluding the companies in techList. Use the exclude: message as shown below:
!fullNoTechList <- fullList exclude: techList; fullNoTechList countproducing the output:
35Notice that now there are only 35 companies. If you wish to know which ones, you can execute the following:
fullNoTechList do: [ name printNL; ];producing the output:
Aetna Life & Cas American Tel & Tel Amoco Corp Atlantic Richfield BellSouth Corp ...To determine which companies are in both techList and highSalesList, execute the following:
techList intersect: highSalesList . do: [ name printNL ] ;You should see:
IBM CorpThe numberElements message is used to extend the list by the variable position which represents the element's position in the list. For example:
subset numberElements do: [ name print: 35 ; position printNL ; ] ;produces the output:
Aetna Life & Cas 1 CIGNA Corp 2 Chrysler Corp 3 Citicorp 4 Ford Motor Company 5 General Motors Corp 6 IBM Corp 7 Travelers Corp 8