Basic Usage Examples¶
After a short example about the basic behavior of AnAugmentedTreeItem (for more details) examples will show how to
- Select items,
- working with these selections
- and viewing them afterwards.
Basic behavior of AnAugmentedTreeItem¶
An ‘augmented’ dictionary or sequence will keep their native behavior, due to the goal of augmentedtree to not interfere with other python modules/packages working with native python mappings and sequences. AnAugmentedTreeItem enhances the nested data.
Accessing AnAugmentedTreeItem by index will return the nested data on basis of its augmented path.
[105]:
from augmentedtree import AugmentedTree
nested_data = {"a": 1, "b": [1, 2, 3], "c": {"d": 3}}
atree = AugmentedTree(nested_data)
print(atree["a"], type(atree["a"]))
print(atree["b"], type(atree["b"]))
print(atree["c"], type(atree["c"]))
1 <class 'int'>
[1, 2, 3] <class 'list'>
{'d': 3} <class 'dict'>
Mappings and sequences can be used like before.
[106]:
print(atree["a"])
print(atree["b"][1])
print(atree["c"]["d"])
1
2
3
The nested exemplary data¶
Within the following examples this nested data will be used.
[107]:
nested_data = {
"A1": {
"B1": {
"C1": {"x11": 11, "x21": 21, "x31": 31},
"C2": {"x12": 12, "x22": 22},
"C3": {"x13": 13},
},
"B2": {
"C1": {"x11": 110, "x21": 210, "x31": 310},
"C2": {"x12": 120, "x22": 220},
},
"B3": {
"C1": {"x11": 1100, "x21": 2100, "x31": 3100}
}
},
"A2": {
"B1": {
"C1": {"x11": 211, "x21": 221, "x31": 231},
"C2": {"x12": 212, "x22": 222},
"C3": {"x13": 213},
}
}
}
Examples on how to¶
Access values using select¶
Selecting items by using a single key.¶
[108]:
atree = AugmentedTree(nested_data)
all_x12_items = atree.select("x12")
all_x12_items.print()
#0 12
#1 120
#2 212
Selecting items by using multiple keys.¶
Keys needs to be in order of their occurrence within the desired items augmented path.
[109]:
atree = AugmentedTree(nested_data)
all_x12_items_at_A2 = atree.select("A2", "x12")
all_x12_items_at_A2.print()
#0 212
[110]:
not_working = atree.select("x12", "A2")
print("Returning nothing", not_working[:])
Returning nothing []
Selecting using UNIX wildcards¶
A selection using the well known and beloved UNIX filename search pattern is supported.
Using the questionmark¶
[111]:
atree = AugmentedTree(nested_data)
allitems_having_a_leading_1 = atree.select("x1?")
allitems_having_a_leading_1.treeitems.print()
#0 /A1/B1/C1/x11
11
#1 /A1/B1/C2/x12
12
#2 /A1/B1/C3/x13
13
#3 /A1/B2/C1/x11
110
#4 /A1/B2/C2/x12
120
#5 /A1/B3/C1/x11
1100
#6 /A2/B1/C1/x11
211
#7 /A2/B1/C2/x12
212
#8 /A2/B1/C3/x13
213
Using a range of numbers¶
Using a range of numbers¶
[112]:
allitems_having_only_1_and_3 = atree.select("x[13][13]")
allitems_having_only_1_and_3.treeitems.print()
#0 /A1/B1/C1/x11
11
#1 /A1/B1/C1/x31
31
#2 /A1/B1/C3/x13
13
#3 /A1/B2/C1/x11
110
#4 /A1/B2/C1/x31
310
#5 /A1/B3/C1/x11
1100
#6 /A1/B3/C1/x31
3100
#7 /A2/B1/C1/x11
211
#8 /A2/B1/C1/x31
231
#9 /A2/B1/C3/x13
213
Getting all unknown items of a specific item¶
new in release 0.2a0
Using a path delimiter with a trailing single asterisk wildcard “/*” selects only items at that level, instead of all sub items (default).
[113]:
all_next_level_subitems_of_b2 = atree.select("B2/*")
all_next_level_subitems_of_b2.treeitems.print()
#0 /A1/B2/C1
C1:
x11: 110
x21: 210
x31: 310
#1 /A1/B2/C2
C2:
x12: 120
x22: 220
If the star * wildcard is used as a stand-alone path part, it will return all sub tree item from its root(s).
[114]:
all_subitems_of_b2 = atree.select("B2", "*")
all_subitems_of_b2.treeitems.print()
#0 /A1/B2/C1
C1:
x11: 110
x21: 210
x31: 310
#1 /A1/B2/C1/x11
110
#2 /A1/B2/C1/x21
210
#3 /A1/B2/C1/x31
310
#4 /A1/B2/C2
C2:
x12: 120
x22: 220
#5 /A1/B2/C2/x12
120
#6 /A1/B2/C2/x22
220
Selecting using regular expression¶
With regular expression a powerful tool for selection is available.
[115]:
from augmentedtree import RegularExpressionParts as REPs
allitems_having_only_1 = atree.select(REPs("x[1]{2}"))
allitems_having_only_1.treeitems.print()
#0 /A1/B1/C1/x11
11
#1 /A1/B2/C1/x11
110
#2 /A1/B3/C1/x11
1100
#3 /A2/B1/C1/x11
211
Select with Or condition¶
Wrapping multiple of path parts with a tuple, a list, an UnixFilePatternPart or a RegularExpressionPart makes these parts behave like an or condition in between them.
select("A", ("B", "C"), "D")
is equal to
A and (B or C) and D
[116]:
from augmentedtree import RegularExpressionParts as REPs
all_x11_items_of_B1_or_Y1 = atree.select(REPs("B1", "Y1"), "x11")
all_x11_items_of_B1_or_Y1.treeitems.print()
#0 /A1/B1/C1/x11
11
#1 /A2/B1/C1/x11
211
Working with selections¶
Accessing single items¶
[117]:
atree = AugmentedTree(nested_data)
all_x12_items = atree.select("x12")
second_found_value = all_x12_items[1]
print(second_found_value)
120
[118]:
second_item = all_x12_items.treeitems[1]
print(second_item)
ValueTreeItem(x12: 120)
Accessing slices¶
Selections can be accessed using slices. For a better readability of scripts AugmentedTree.ALL_ITEMS can be used.
[119]:
from augmentedtree import ALL_ITEMS
atree = AugmentedTree(nested_data)
all_x12_items = atree.select("x12")
all_values = all_x12_items[ALL_ITEMS]
print(all_values)
[12, 120, 212]
[120]:
all_except_last = all_x12_items[:-1]
print(all_except_last)
[12, 120]
Setting multiple values at different locations at once¶
[121]:
from copy import deepcopy
temp_nested_data = deepcopy(nested_data)
atree = AugmentedTree(temp_nested_data)
# Select items
all_x11_items = atree.select("x11")
# Set all items to a new values
all_x11_items[ALL_ITEMS] = "My key is x11."
atree.print()
{..}
A1:
B1:
C1:
x11: My key is x11.
x21: 21
x31: 31
C2:
x12: 12
x22: 22
C3:
x13: 13
B2:
C1:
x11: My key is x11.
x21: 210
x31: 310
C2:
x12: 120
x22: 220
B3:
C1:
x11: My key is x11.
x21: 2100
x31: 3100
A2:
B1:
C1:
x11: My key is x11.
x21: 221
x31: 231
C2:
x12: 212
x22: 222
C3:
x13: 213
[122]:
all_x11_items[1:3] = "A value set by using slicing."
atree.print()
{..}
A1:
B1:
C1:
x11: My key is x11.
x21: 21
x31: 31
C2:
x12: 12
x22: 22
C3:
x13: 13
B2:
C1:
x11: A value set by using slicing.
x21: 210
x31: 310
C2:
x12: 120
x22: 220
B3:
C1:
x11: A value set by using slicing.
x21: 2100
x31: 3100
A2:
B1:
C1:
x11: My key is x11.
x21: 221
x31: 231
C2:
x12: 212
x22: 222
C3:
x13: 213
Viewing treeitems¶
AnAugmentedTreeItem will give you a different output in whether you use print(treeitem)
or treeitem.print()
.
The standard output resembles the nested data wrapped by AnAugmentedTreeItem. An exception is a ValueTreeItem in which its key (primekey) is also print out for more convenience.
[123]:
root_level = {
"ridiculous-level": {
"ludicrous-level": "They've gone into plaid."
}
}
spacetree = AugmentedTree(root_level)
ridiculous_item = spacetree.children["ridiculous-level"]
ludicrous_item = ridiculous_item.children["ludicrous-level"]
print(spacetree)
print(ridiculous_item)
print(ludicrous_item)
AugmentedTree({'ridiculous-level': {'ludicrous-level': "They've gone into plaid."}})
MappingTreeItem({'ludicrous-level': "They've gone into plaid."})
ValueTreeItem(ludicrous-level: They've gone into plaid.)
Using AnAgumentedTreeItem’s print method gives a different output.
[124]:
print("# spacetree")
spacetree.print()
print("# ridiculous_treeitem")
ridiculous_item.print()
print("# ludicrous_treeitem")
ludicrous_item.print()
# spacetree
{..}
ridiculous-level:
ludicrous-level: They've gone into plaid.
# ridiculous_treeitem
ridiculous-level:
ludicrous-level: They've gone into plaid.
# ludicrous_treeitem
They've gone into plaid.
Sorting tree item selections¶
new in release 0.2a0
The main purpose of the sort-method is to sort selections. If the nested data should be sorted, its more efficient to use specific packages and re-augment the sorted result. In many cases a sorted result of a selection is desired.
Tree items can be sorted using the sort method of AugmentedTreeItem or AugmentedItemSelection. By default the tree items are sorted in regard of their augmented_path.
The current implementation does not sort the nested data itself. It sorts the tree items. It can be compared to a reorganized view, while the original data keeps its order.
Exemplary behavior¶
This example shows a simple nested structure with 6 leafs.
[125]:
from augmentedtree import AugmentedTree
data = {
"b": {
"a-1": 1,
"b-1": 2
},
"a": {
"a-2": 3,
"a-13": 4,
"b-2": 5,
"b-13": 6,
}
}
a_tree = AugmentedTree(data)
a_tree.print()
{..}
b:
a-1: 1
b-1: 2
a:
a-2: 3
a-13: 4
b-2: 5
b-13: 6
The tree items inherits the order of the given structure.
[126]:
a_tree.treeitems.print()
#0 /b
b:
a-1: 1
b-1: 2
#1 /b/a-1
1
#2 /b/b-1
2
#3 /a
a:
a-2: 3
a-13: 4
b-2: 5
b-13: 6
#4 /a/a-2
3
#5 /a/a-13
4
#6 /a/b-2
5
#7 /a/b-13
6
Sorting the tree affects the global order of the tree items, but not the local order or the nested data itself.
[127]:
sorting_tree = a_tree.sort()
sorting_tree.print()
{..}
b:
a-1: 1
b-1: 2
a:
a-2: 3
a-13: 4
b-2: 5
b-13: 6
[128]:
sorting_tree.treeitems.print()
#0 /a
a:
a-2: 3
a-13: 4
b-2: 5
b-13: 6
#1 /a/a-13
4
#2 /a/a-2
3
#3 /a/b-13
6
#4 /a/b-2
5
#5 /b
b:
a-1: 1
b-1: 2
#6 /b/a-1
1
#7 /b/b-1
2
Basic usage of sorting¶
The main purpose is to sort selections. The default sorting order is based on the augmented path.
[129]:
all_bees = a_tree.select("b-*").sort()
all_bees.treeitems.print()
#0 /a/b-13
6
#1 /a/b-2
5
#2 /b/b-1
2
A different sorting order might be desired, which can be achieved using the Callable[[PathMapItem], int] interface.
[130]:
from augmentedtree.treeitemselection import PathMapItem
def sort_by_trailing_item_number(path_map_item: PathMapItem) -> int:
number_characters = path_map_item.primekey.split("-")[1]
try:
return int(number_characters)
except TypeError:
return 0
all_bees = a_tree.select("b-*").sort(sorting_method=sort_by_trailing_item_number)
all_bees.treeitems.print()
#0 /b/b-1
2
#1 /a/b-2
5
#2 /a/b-13
6