The container package provides specialized data structures that technically are all derived from the Container
class. As such they share all of the container functions with some of them being overridden to account for the specialized data structure. In particular, all of the derived structures still provide positional element access to still behave similar to base R lists.
Deques (double ended queues) are a generalization of stacks and queues and therefore also can be used to mimic these.
A stack is a last-in-first-out (LIFO) data structure with two basic operations, push and pop, which in this case are mimicked with ref_add
and ref_pop
.
# Mimic stack
s = deque()
s
# ||
ref_add(s, 1)
ref_add(s, 2)
s
# |1, 2|
ref_pop(s)
# [1] 2
ref_pop(s)
# [1] 1
s
# ||
A queue is a first-in-first-out (FIFO) data structure with two basic operations, push and pop_left (or enqueue and dequeue), which in this case are mimicked with ref_add
and ref_popleft
.
# Mimic queue
q = deque()
q
# ||
ref_add(q, 1)
ref_add(q, 2)
q
# |1, 2|
ref_popleft(q)
# [1] 1
ref_popleft(q)
# [1] 2
q
# ||
A double-ended queue works on both ends and also provides rotate and reverse operations.
d = as.deque(1:4)
d
# |1L, 2L, 3L, 4L|
rev(d)
# |4L, 3L, 2L, 1L|
rotate(d, 2)
# |3L, 4L, 1L, 2L|
All elements of a set are unique. Basic set operations are provided.
s1 = setnew(1, "1", 2, cars)
s2 = setnew(1, 2, 3, iris)
s1 & s2
# {1, 2}
s1 | s2
# {1, "1", 2, <<data.frame(50x2)>>, 3, <<data.frame(150x5)>>}
s1 - s2
# {"1", <<data.frame(50x2)>>}
It is important to note that set comparison for the standard set is not order-invariant, e.g.:
s1 = setnew(1, 2, 3)
s2 = setnew(2, 1, 3)
s1 == s2
# [1] FALSE
This property is intended to allow positional access also in sets (remember that technically the 'Set' class is derived from 'Container').
s1[1:2]
# {1, 2}
s2[1:2]
# {2, 1}
If you want order-invariant sets, just use the OrderedSet
.
os1 = as.orderedset(s1)
os2 = as.orderedset(s2)
os1
# {1, 2, 3}
os2
# {1, 2, 3}
os1 == os2
# [1] TRUE
Last but not least, the container
package only covers a small range of sets and set functions. For a wide range of set functionality and data structures such as fuzzy sets, multisets, customizable sets and intervals, please refer to the sets package by David Meyer.
In a dictionary, each element is mapped to a name. In the container
package, dicts are always sorted by name, either after initialization ...
d = dict(z = 2, a = 10)
d
# {a = 10, z = 2}
... or when new elements are added.
d[["x"]] = 1
d
# {a = 10, x = 1, z = 2}
If added using the add
function, a name clash is signaled to prevent overwriting existing elements.
add(d, z = 3)
# Error: name 'z' exists already
To overwrite, you can use one of three approaches.
d[["z"]] = 3
replace_at(d, z = 3)
# {a = 10, x = 1, z = 3}
update(d, dict(z = 3))
# {a = 10, x = 1, z = 3}
By design, elements can be accessed by name or position, the latter always based on the ordered elements.
d["x", "a"]
# {a = 10, x = 1}
d[2:1]
# {a = 10, x = 1}
add(d, b = 3)[2:1]
# {a = 10, b = 3}
For more examples see the vignette Manage parameter lists with dict.