---
title: "Deque, Set, and Dict"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 4
description: >
    Explore the specialized data structures provided by {container}.
    These are,
    Deque for efficient double-ended queue operations,
    Set for unique elements with basic set operations and order-sensitive
    behavior, and
    Dict, a dictionary-like structure, offering ordered key-value pairs
    and safe operations for managing named elements.
vignette: >
  %\VignetteIndexEntry{Deque, Set, and Dict}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r knitr-setup, include = FALSE}
require(container)
knitr::opts_chunk$set(
  comment = "#",
  prompt = FALSE,
  tidy = FALSE,
  cache = FALSE,
  collapse = TRUE
)

old <- options(width = 100L)
```

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.


## Deque

Deques (double ended queues) are a generalization of stacks and queues and
therefore also can be used to mimic these.

### Stack

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`.

```{r}
# Mimic stack
s = deque()
s
ref_add(s, 1)
ref_add(s, 2)
s

ref_pop(s)
ref_pop(s)
s
```

### Queues

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`.

```{r}
# Mimic queue
q = deque()
q
ref_add(q, 1)
ref_add(q, 2)
q

ref_popleft(q)
ref_popleft(q)
q
```


A double-ended queue works on both ends and also provides rotate and reverse
operations.

```{r}
d = as.deque(1:4)
d
rev(d)
rotate(d, 2)
```



## Set

All elements of a set are unique. Basic set operations are provided.

```{r}
s1 = setnew(1, "1", 2, cars)
s2 = setnew(1,      2, 3, iris)

s1 & s2
s1 | s2
s1 - s2
```

It is important to note that set comparison for the standard set is not
order-invariant, e.g.:
```{r}
s1 = setnew(1, 2, 3)
s2 = setnew(2, 1, 3)
s1 == s2
```

This property is intended to allow positional access also in sets (remember
that technically the 'Set' class is derived from 'Container').
```{r}
s1[1:2]
s2[1:2]
```

If you want order-invariant sets, just use the `OrderedSet`.

```{r}
os1 = as.orderedset(s1)
os2 = as.orderedset(s2)
os1
os2
os1 == os2
```

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](https://CRAN.R-project.org/package=sets) package by David Meyer.


## Dict

In a dictionary, each element is mapped to a name. In the {container} package,
dicts are always sorted by name, either after initialization ...

```{r}
d = dict(z = 2, a = 10)
d
```

... or when new elements are added.
```{r}
d[["x"]] = 1
d
```

If added using the `add` function, a name clash is signaled to prevent
overwriting existing elements.
```{r, error = TRUE}
add(d, z = 3)
```

To overwrite, you can use one of three approaches.
```{r}
d[["z"]] = 3
replace_at(d, z = 3)
update(d, dict(z = 3))
```

By design, elements can be accessed by name or position, the latter always
based on the ordered elements.

```{r}
d["x", "a"]
d[2:1]

add(d, b = 3)[2:1]
```

For more examples see the vignette
[Manage parameter lists with dict](https://rpahl.github.io/container/articles/v03-parameter-list.html).

```{r, include = FALSE}
options(old)
```
