Next | Previous

Dictionaries

Blade dictionaries are built on powerful hashtables with fast key lookups. Creating Blade dictionaries are extremely similar to how you create objects in JavaScript and for developers coming from that language will find Blade dictionaries very familiar.

Reference

Constructing a dictionary

Blade dictionaries are arbitary key-value pairs separated by colons (:) enclosed in braces ({}).

For example:

%> {'name': 'Blade', 'version': 0.5}
{name: Blade, version: 0.5}
%> {}    # empty dictionary
{}

While dictionary values can be any valid Blade object, keys can only be one of String, Number or Boolean.

For example:

%> {0: 'number', false: 'boolean', 'key': 'string'}
{0: number, false: boolean, key: string}

For string keys in a dictionary, the quotation may be excluded given that the string contains no space or any non alphanumeric character or the unquoted version equals to a boolean value.

For example:

%> {country: 'Nigeria', dial_code: 234, in_africa: true}
{country: Nigeria, dial_code: 234, in_africa: true}

Automatic value assignment

Sometimes when creating a dictionary, it is very common to have keys that already match the name of a variable that already exists in scope. For example:

%> var name = 'Paulina'
%> var my_dict = {name: name}
%> my_dict
{name: Paulina}

Because of how common and frequent developers do this, Blade has an automatic value assignment feature for dictionaries that allow you to assing variables to dictionary keys if they are already within scope without rewriting them.

For example,

%> var name = 'Kagawa'
%> {name}
{name: Kagawa}

Accessing members of a Dictionary

Each key in a dictionary is a property of the given dictionary and as such, dictionary like strings and lists support index access.

For example:

%> var a = {name: 'Blade', version: 0.5}
%> a['name']
'Blade'

And they also support property access whenever the key is a string. For example, the above a['name'] could also be written as:

%> a.name
'Blade'

Looping through dictionaries

There are two ways to loop through a dictionary in Blade. We can loop through the dictionary itself using the specialized for loop, of loop through its keys using any of the while or iter loop.

Below is an example looping through the dictionary itself using the for loop.

%> var person = {name: 'Ceaser', birth: '29AD', nation: 'Rome', position: 'Emperor'}
%> for x, y in person {
..   print(x, '=', y)
.. }
name = Ceaser
birth = 29AD
nation = Rome
position = Emperor

Unlike strings and lists, note that this for loop takes two variables. This is to allow us take the key into the first and the value into the second variable respectively.

If we only want to loop through the values without concern for the keys, we can use a single variable to hold our value and still iterate correctly. Note however that the corresponding key information will be lost in the loop.

For example:

%> for x in person {
..   echo x
.. }
'Ceaser'
'29AD'
'Rome'
'Emperor'

The following example loops through the dictionary by looping through the keys of the dictionary.
%> var keys = person.keys()
%> iter var i = 0; i < keys.length(); i++ {
..   print(keys[i], '=', person[keys[i]])
.. }
name = Ceaser
birth = 29AD
nation = Rome
position = Emperor

The technique presented above is to walk through the keys of the dictionary and use the current key to index the dictionary. While the example uses the iter loop, the same technique applies to the while loop.

Dictionary methods

Blade dictionaries comes with a lot of power packed methods like other objects. The methods are detailed below.

.length()

Returns the length of the dictionary. The length of a Blade dictionary is equal to the number of keys it contains. i.e. dict.length() == dict.keys().length().

For example:

%> {name: 'Blade', version: 1}.length()
2
.add(key: any, value: any)

Adds a new key-value pair to the dictionary with the given key and value.

For example:

%> var dict = {}
%> dict.add('name', 'Blade')
%> dict
{name: Blade}
.set(key: any, value: any)

Sets the value of the given key to the given value in the dictionary. If there is no exisiting entry for the key in the dictionary, a new entry will be added.

For example:

%> dict.set('name', 'New Blade')
%> dict
{name: New Blade}
%> dict.set('version', 1)
%> dict
{name: New Blade, version: 1}

@note: dict.set(x, y) is equivalent to the following Blade code.

%> if dict.contains(x) {
..   dict[x] = 1
.. } else {
..   dict.add(x, 1)
.. }
.clear()

Clears the content of the dictionary.

For example:

%> var a = {name: 'Blade'}
%> a
{name: Blade}
%> a.clear()
%> a
{}
.clone()

Returns a new dictionary which is a deep copy of the original dictionary.

For example:

%> var new_dict = dict.clone()
%> new_dict
{name: New Blade, version: 1}
.compact()

Returns a new dictionary that contains every key-value pair in the original dictionary except for keys whose associated value is nil.

For example:

%> var dict2 = {name: 'James', age: 20, address: nil, country: nil}
%> dict2.compact()
{name: James, age: 20}
.contains(x: any)

Returns true if any of the keys in the dictionary is equal to x, false otherwise.

For example:

%> dict2.contains('name')
true
%> dict2.contains('street')
false
.extend(x: dict)

Adds all key-value pairs in dictionary x to the original dictionary.

For example:

%> var dict = {name: 'Blade'}
%> dict.extend({version: 1})
%> dict
{name: Blade, version: 1}
.get(key: any [, default: any])

Returns the value of the given key in the dictionary. If the given key is not defined in the dictionary and the default value is given, the default value will be returned. Otherwise, nil is returned.

For example:

%> dict.get('version')   # value exists
1
%> dict.get('age')   # value does not exist
%> dict.get('age', 6)   # value does not exist, but default is given
6
%> dict.get('version', 1.1)   # value exists and default is given
1
.keys()

Returns a list containing the keys in the dictionary.

For example:

%> dict.keys()
[name, version]
.values()

Returns a list containing the value of all keys in the dictionary.

For example:

%> dict.values()
[Blade, 1]
.remove(key: any)

Removes a given key and it's corresponding value from the dictionary and returns the value of the key.

For example:

%> dict = {username: 'james', email: 'a@b.c', active: true}
%> dict.remove('active')
true
%> dict
{username: james, email: a@b.c}
.is_empty()

Returns true if the dictionary is empty, otherwise returns false.

For example:

%> dict.is_empty()
false
%> {}.is_empty()
true
.find_key(x: any)

Returns the key whose value is equal to x in the dictionary or nil if no key has the value x.

For example:

%> dict.find_key('james')
'username'
%> dict.find_key('camel')
.to_list()

Returns a list that contains a list of key and a list of values from the dictionary.

For example:

%> var dict = {username: 'james', email: 'a@b.c'}
%> dict.to_list()
[[username, email], [james, a@b.c]]
.each(callback: function)

Executes the provided callback once for each key/value pair in the dictionary.

For example:

%> var info = {name: 'Pius', age: 46}
%> 
%> # calling each without using data
%> echo info.each(@{
..   echo 'Iterating dictionary'
.. })
'Iterating dictionary'
'Iterating dictionary'

The callback function can accept zero or more arguments. When the callback function accepts arguments, the current value will be passed to the first parameter whenever the callback is called.

For example:

%> # calling each for values only
%> echo info.each(@(value) {
..   echo value
.. })
'Pius'
46

If the callback function has more than one parameter, the second parameter is assigned the value of the key of the current value in the dictionary.

For example:

%> # calling each for both key and value
%> echo info.each(@(value, key) {
..   echo '${key} = ${value}'
.. })
'name = Pius'
'age = 46'
.filter(callback: function)

Returns a portion (shallow copy) of the dictionary filtered down to the key/value pairs in the dictionary that pass the test done by the callback function.

The filter callback function accepts and is passed the same values as .each().

The callback function is required to return a value that can resolves as true for elements that should be kept or resolves as false for elements that should not be kept.

If no element passes the test in the callback, an empty dictionary is returned.

For example:

%> var info = {name: 'Pius', age: 46}
%> 
%> echo info.filter(@(value) {
..   return is_number(value)
.. })
{age: 46}
.some(callback: function)

Returns true if at least one key/value pair in the dictionary pases the test conducted by the callback function. The callback function is required to return a value that can resolves as true for elements that should be kept or resolves as false for elements that should not be kept.

The some callback function accepts and is passed the same values as .each().

For example:

%> var info = {name: 'Pius', age: 46}
%> 
%> echo info.some(@(value) {
..   return is_bool(value)
.. })
false
%> 
%> echo info.some(@(value, key) {
..   return key == 'age'
.. })
true
.every(callback: function)

Returns true if all the key/value pair in the dictionary pases the test conducted by the callback function. The callback function is required to return a value that can resolves as true for elements that should be kept or resolves as false for elements that should not be kept.

The every callback function accepts and is passed the same values as .each().

For example:

%> var scores = {kally: 56, anna: 79, bolf: 19}
%> 
%> echo scores.every(@(value) {
..   return value > 70
.. })
false
%> 
%> echo scores.every(@(value, key) {
..   return key.length() >= 3 and value > 0
.. })
true
.reduce(callback: function [, initial_value: any = nil])

Executes the reducer callback function on every key/value pair in the dictionary in order, passing in the return value from the previous calculation on the preceeding element and returning a single value equal to the result of running the reducer callback across all elements.

This method is the same as the list.reduce() method except that this method works on dictionaries and key/value pairs. For dictionaries, keys are used instead of indices.

See list.reduce() for more information about reduce()



Previous Topic | Next Topic