How do I Display an Array in Human Readable Form?

This lesson describes how to implement a short recursive algorithm to display arbitrarily nested arrays that contain printable data. Sample code is provided.

Introduction

It is often convenient to represent complex data sets as nested array structures. This allows information to be grouped in a logical form that is easily accessible from within a LiveCode application. As the data of such an array structure grows, it can quickly become difficult for a human reader to interpret the data and determine the array structure. Fortunately, it is very easy to write a generic function that decomposes complex array structures into an easily readable form.

Creating the Array Data

The structure and depth of the array can be chosen freely to meet the requirements of the data that is to be stored.

In the following example, the data represents an arrangement that may be present in an application that is used to process purchases of online book orders.

The data stored contains: The first name, the last name, the country in which the customer lives, the books a customer purchased, the currency in which the books were paid for and the payments that were made for each book. In this example, the book seller allows for books to be paid for in installments.

# declare the variable that stores the array

local tCustomerDataArray

# populate the customer names

put "John" into tCustomerDataArray["1"]["address"]["first_name"]

put "Smith" into tCustomerDataArray["1"]["address"]["last_name"]

put "Peter" into tCustomerDataArray["2"]["address"]["first_name"]

put "Brown" into tCustomerDataArray["2"]["address"]["last_name"]

put "Martin" into tCustomerDataArray["3"]["address"]["first_name"]

put "Adamson" into tCustomerDataArray["3"]["address"]["last_name"]

put "Julia" into tCustomerDataArray["4"]["address"]["first_name"]

put "King" into tCustomerDataArray["4"]["address"]["last_name"]

# populate the customer country details

put "Scotland" into tCustomerDataArray["1"]["address"]["country"]

put "Germany" into tCustomerDataArray["2"]["address"]["country"]

put "England" into tCustomerDataArray["3"]["address"]["country"]

put "Sweden" into tCustomerDataArray["4"]["address"]["country"]

# populate the customer order details

put "Walking in Scotland" into tCustomerDataArray["1"]["orders"]["1"]["book"]

put "The Great Outdoors" into tCustomerDataArray["1"]["orders"]["2"]["book"]

put "Kilts and Stuff" into tCustomerDataArray["1"]["orders"]["3"]["book"]

put "1001 Jokes" into tCustomerDataArray["2"]["orders"]["1"]["book"]

put "Makeup and Fashion" into tCustomerDataArray["3"]["orders"]["1"]["book"]

put "Meat Ball Recipes" into tCustomerDataArray["4"]["orders"]["1"]["book"]

put "Ice Hotels DIY" into tCustomerDataArray["4"]["orders"]["2"]["book"]

# populate the customer payments

put "pounds" into tCustomerDataArray["1"]["orders"]["1"]["currency"]

put "10.00" into tCustomerDataArray["1"]["orders"]["1"]["payments"]["1"]

put "pounds" into tCustomerDataArray["1"]["orders"]["2"]["currency"]

put "15.00" into tCustomerDataArray["1"]["orders"]["2"]["payments"]["1"]

put "pounds" into tCustomerDataArray["1"]["orders"]["3"]["currency"]

put "7.00" into tCustomerDataArray["1"]["orders"]["3"]["payments"]["1"]

put "7.00" into tCustomerDataArray["1"]["orders"]["3"]["payments"]["2"]

put "euro" into tCustomerDataArray["2"]["orders"]["1"]["currency"]

put "5.00" into tCustomerDataArray["2"]["orders"]["1"]["payments"]["1"]

put "5.00" into tCustomerDataArray["2"]["orders"]["1"]["payments"]["2"]

put "pounds" into tCustomerDataArray["3"]["orders"]["1"]["currency"]

put "20.00" into tCustomerDataArray["3"]["orders"]["1"]["payments"]["1"]

put "krona" into tCustomerDataArray["4"]["orders"]["1"]["currency"]

put "12.00" into tCustomerDataArray["4"]["orders"]["1"]["payments"]["1"]

put "krona" into tCustomerDataArray["4"]["orders"]["2"]["currency"]

put "17.00" into tCustomerDataArray["4"]["orders"]["2"]["payments"]["1"]  

This array represents the information of four customers and their purchases.

Decomposing the Array Data

There are potentially many ways of decomposing array data into a human readable form, and the representation chosen depends on personal preference and the data structure that is to be displayed.

The code in this lesson is generic and can be used on a large range of arrays. Data is processed in two ways:

1. Indent the data from left to right, depending on the depth at which the data is stored in the array.

2. Group information together depending on how close it lies together in the array structure.

function displayArrayData pArray, pIndent

# create the variable that loops through the keys in the array

local tKey

if pArray is an array then

# print information to indicate that we are entering a new nested level of the array

get "Array" & return

# print full stops that allow the reader to track the depth of an element

put "." after pIndent

# create the indentation

put tab after pIndent

repeat for each key tKey in pArray

# call displayArrayData with a nested array

put format("%s[%s] => %s\n", pIndent, tKey, displayArrayData (pArray[tKey], pIndent)) after it

end repeat

delete the last char of it

return it

else

return pArray

end if

end displayArrayData

The level of indentation and its formatting is explicitly controlled by output lines in the function. Information grouping is implicitly generated as a result of  depth-first search exploration of the array data structure.

The Formatted Output

The output from displayArrayData is written to the LiveCode Message Box and is structured as follows:

Array

. [1] => Array

. . [address] => Array

. . . [first_name] => John

. . . [last_name] => Smith

. . . [country] => Scotland

. . [orders] => Array

. . . [1] => Array

. . . . [payments] => Array

. . . . . [1] => 10.00

. . . . [book] => Walking in Scotland

. . . . [currency] => pounds

. . . [2] => Array

. . . . [payments] => Array

. . . . . [1] => 15.00

. . . . [book] => The Great Outdoors

. . . . [currency] => pounds

. . . [3] => Array

. . . . [payments] => Array

. . . . . [1] => 7.00

. . . . . [2] => 7.00

. . . . [book] => Kilts and Stuff

. . . . [currency] => pounds

. [2] => Array

. . [address] => Array

. . . [first_name] => Peter

. . . [last_name] => Brown

. . . [country] => Germany

. . [orders] => Array

. . . [1] => Array

. . . . [payments] => Array

. . . . . [1] => 5.00

. . . . . [2] => 5.00

. . . . [book] => 1001 Jokes

. . . . [currency] => euro

. [3] => Array

. . [address] => Array

. . . [first_name] => Martin

. . . [last_name] => Adamson

. . . [country] => England

. . [orders] => Array

. . . [1] => Array

. . . . [payments] => Array

. . . . . [1] => 20.00

. . . . [book] => Makeup and Fashion

. . . . [currency] => pounds

. [4] => Array

. . [address] => Array

. . . [first_name] => Julia

. . . [last_name] => King

. . . [country] => Sweden

. . [orders] => Array

. . . [1] => Array

. . . . [payments] => Array

. . . . . [1] => 12.00

. . . . [book] => Meat Ball Recipes

. . . . [currency] => krona

. . . [2] => Array

. . . . [payments] => Array

. . . . . [1] => 17.00

. . . . [book] => Ice Hotels DIY

. . . . [currency] => krona

The data is logically grouped, and the data depth is indicated by the number of full stops in front of each entry. For example, address data contains the first_name, the last_name and the country.

Note: If you do not know how the grouping was created or mapped to the array, please refer to the source array structure and compare it to the output that is shown here.

2 Comments

Dennis Wurster

Can you provide the syntax of your function call?

In the case of the article, I'm expecting it to be something like

displayArrayData tCustomerDataArray, "."

and I'd expect the full line of code to be something like

put displayArrayData tCustomerDataArray, "." into field "results"

Elanor Buchanan

Hi Dennis

You call a function in LiveCode like this:

displayArrayData(tCustomerArrayData,".")

the full line of code would be

put displayArrayData(tCustomerArrayData,".") into field "results"

In this case you don't actually need to pass pIndent when you first call the function, pIndent is used when the function is called recursively but can be left empty in the initial call.

I hope that helps.

Elanor

Add your comment

E-Mail me when someone replies to this comment