Lists
Julius Schmid
In contrast to a vector, in which all elements must be of the same
mode, R’s list structure can combine objects of different types.
Creating Lists
Technically, a list is a vector. Ordinary vectors—those of the type
we’ve been using so far in this book—are termed atomic vectors, since
their components cannot be broken down into smaller components. In
contrast, lists are referred to as recursive vectors.
For our first look at lists, let’s consider an employee database. For
each employee, we wish to store the name, salary, and a Boolean
indicating union membership. Since we have three different modes
here—character, numeric, and logical — it’s a perfect place for using
lists. Our entire database might then be a list of lists, or some other
kind of list such as a data frame, though we won’t pursue that here. We
could create a list to represent our employee, Marco, this way:
j <- list(name="Marco", salary=72000, union=T)
We could print out j, either in full or by component:
Start by print j out in full. This is done by just entering the list
name j:
j
$name
[1] "Marco"
$salary
[1] 72000
$union
[1] TRUE
Now we return the different list entries individually. We do this in
the same way, as if we would access a column of a data frame, running
list_name$entry.
- Return the name entry:
j$name
[1] "Marco"
- Return the salary entry:
j$salary
[1] 72000
- Return the union entry:
j$union
[1] TRUE
General List Operations
Now that you’ve seen a simple example of creating a list, let’s look
at how to access and work with lists.
List Indexing
You can access a list component in several different ways. The first
method is the one we have seen above.
j$salary
[1] 72000
The second method is the syntax list_name[[“entry”]]:
j[["salary"]]
[1] 72000
The third way is using the index of the index of the entry that is to
be returned. In this case, salary is the second entry, hence we return
the entry with index 2:
j[[2]]
[1] 72000
We can refer to list components by their numerical indices, treating
the list as a vector. However, note that in this case, we use double
brackets instead of single ones.
In summary, there are three ways to access an individual component c
of a list lst and return it in the data type of c: list_name$entry,
list_name[[“entry”]], and list_name[[index]].
Adding and Deleting List Elements
The operations of adding and deleting list elements arise in a
surprising number of contexts. This is especially true for data
structures in which lists form the foundation, such as data frames and R
classes.
New components can be added after a list is created.
z <- list(first="character",second=5)
z
$first
[1] "character"
$second
[1] 5
We can add an additional entry by assigning a value to a yet unnamed
list entry:
z$third <- "soccer"
z
$first
[1] "character"
$second
[1] 5
$third
[1] "soccer"
We confirm that a third element was added to the list named
third.
Adding components can also be done via a vector index:
z[[4]] <- 32
z[5:7] <- c(FALSE,TRUE,TRUE)
z
$first
[1] "character"
$second
[1] 5
$third
[1] "soccer"
[[4]]
[1] 32
[[5]]
[1] FALSE
[[6]]
[1] TRUE
[[7]]
[1] TRUE
You can also delete a list component by setting it to NULL.
z$second <- NULL
z
$first
[1] "character"
$third
[1] "soccer"
[[3]]
[1] 32
[[4]]
[1] FALSE
[[5]]
[1] TRUE
[[6]]
[1] TRUE
You can also concatenate lists.
c(list("Lucas", 83000, T),list(5))
[[1]]
[1] "Lucas"
[[2]]
[1] 83000
[[3]]
[1] TRUE
[[4]]
[1] 5
Getting the Size of a List
Since a list is a vector, you can obtain the number of components in
a list via length().
length(j)
[1] 3
length(z)
[1] 6
Accessing List Components and Values
If the components in a list do have tags, as is the case with name,
salary, and union for j, you can obtain them via names():
names(j)
[1] "name" "salary" "union"
To obtain the values, use unlist():
ulj <- unlist(j)
ulj
name salary union
"Marco" "72000" "TRUE"
We apply the class() function to return the data type of the
list:
class(ulj)
[1] "character"
On the other hand, if all the components are numbers, we would get
numeric as an output.
z <- list(a=8,b=16,c=5)
class(y)
[1] "numeric"
We can apply the unlist() function, to not interpret the variable as
a list:
y <- unlist(z)
y
a b c
8 16 5
Same as above, we apply the class() function for the unlisted y, and
we get the same output as if we apply the class() function to the list
y:
class(y)
[1] "numeric"
So the output of unlist() in this case was a numeric vector. What
about a mixed case?
w <- list(a=52,b="random character")
wu <- unlist(w)
class(wu)
[1] "character"
Since there is one character element in the array (“random
character”), all components are interpreted as characters.
Let us print out the unlisted wu:
wu
a b
"52" "random character"
Both 52 and random character are interpreted as character
strings.
Applying Functions to Lists
Two functions are handy for applying functions to lists: lapply and
sapply.
Using the lapply() and sapply()
Functions
The function lapply() (for list apply) works like the matrix apply()
function, calling the specified function on each component of a list (or
vector coerced to a list) and returning another list. Here’s an
example:
lapply(list(5:7,25:35),median)
[[1]]
[1] 6
[[2]]
[1] 30
R applied median() to 5:7 and to 25:35, returning a list consisting
of 6 and 30. In some cases, such as the example here, the list returned
by lapply() could be simplified to a vector or matrix. This is exactly
what sapply() (for simplified [l]apply) does.
sapply(list(5:7,25:35),median)
[1] 6 30
Using sapply(), rather than applying the function directly, gave us
the desired matrix form in the output.
Extended Example: Back to the Abalone
Data
Let’s use the lapply() function in our abalone gender example. Recall
that at one point in that example, we wished to know the indices of the
observations that were male, female, and infant. For an easy
demonstration, let’s use the same test case: a vector of genders.
g <- c("M","I","F","I","M","F","F")
lapply(c("F","M","I"),function(gender) which(g==gender))
[[1]]
[1] 3 6 7
[[2]]
[1] 1 5
[[3]]
[1] 2 4
The lapply() function expects its first argument to be a list. Here
it was a vector, but lapply() will coerce that vector to a list form.
Also, lapply() expects its second argument to be a function. This could
be the name of a function, as you saw before, or the actual code, as we
have here. This is an anonymous function, which you’ll learn more about
in Section 7.13.
Then lapply() calls that anonymous function on “F”, then on “M”, and
then on “I”. In that first case, the function calculates which(g==“F”),
giving us the vector of indices in g of the females. After determining
the indices for the males and infants, lapply() will return the three
vectors in a list.
Note that even though the object of our main attention is the vector
g of genders, it is not the first argument in the lapply() call in the
example. Instead, that argument is an innocuous-looking vector of the
three possible gender encodings. By contrast, g is mentioned only
briefly in the function, as the second actual argument. This is a common
situation in R. An even better way to do this will be presented in
Section 6.2.2.
Recursive Lists
Lists can be recursive, meaning that you can have lists within lists.
Here’s an example:
b <- list(u = 5, v = 12)
c <- list(w = 13)
a <- list(b,c)
The list b has two entries, the list c has one entry. a then combines
lists b and c in a new list of lists. Let us see what this looks like
when we return it:
a
[[1]]
[[1]]$u
[1] 5
[[1]]$v
[1] 12
[[2]]
[[2]]$w
[1] 13
The two lists b ([[1]]) and c([[2]]) are returned, where b has two
components. Let us print the length of a:
length(a)
[1] 2
The length of a is 2. This is because a contains 2 lists.
The code makes a into a two-component list, with each component
itself also being a list. The concatenate function c() has an optional
argument recursive, which controls whether flattening occurs when
recursive lists are combined.
Now let us create a list p with 3 entries, where one component is a
list itself:
p <- c(list(a=4,b=1,c=list(d=25,e=7)))
p
$a
[1] 4
$b
[1] 1
$c
$c$d
[1] 25
$c$e
[1] 7
The length of p is 3, since p has three entries:
length(p)
[1] 3
However, if we set the optional parameter recursive to TRUE, our list
has 4 components.
p2 = c(list(a=4,b=1,c=list(d=25,e=7)),recursive=T)
p2
a b c.d c.e
4 1 25 7
We confirm this by applying the length() function again:
length(p2)
[1] 4
In the first case, we accepted the default value of recursive, which
is FALSE, and obtained a recursive list, with the c component of the
main list itself being another list. In the second call, with recursive
set to TRUE, we got a single list as a result; only the names look
recursive. (It’s odd that setting recursive to TRUE gives a nonrecursive
list.) Recall that our first example of lists consisted of an employee
database. I mentioned that since each employee was represented as a
list, the entire database would be a list of lists. That is a concrete
example of recursive lists.
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKKipMaXN0cyoqCgpKdWxpdXMgU2NobWlkCgpJbiBjb250cmFzdCB0byBhIHZlY3RvciwgaW4gd2hpY2ggYWxsIGVsZW1lbnRzIG11c3QgYmUgb2YgdGhlIHNhbWUgbW9kZSwgUuKAmXMgbGlzdCBzdHJ1Y3R1cmUgY2FuIGNvbWJpbmUgb2JqZWN0cyBvZiBkaWZmZXJlbnQgdHlwZXMuCgoqKipDcmVhdGluZyBMaXN0cyoqKgoKVGVjaG5pY2FsbHksIGEgbGlzdCBpcyBhIHZlY3Rvci4gT3JkaW5hcnkgdmVjdG9yc+KAlHRob3NlIG9mIHRoZSB0eXBlIHdl4oCZdmUgYmVlbiB1c2luZyBzbyBmYXIgaW4gdGhpcyBib29r4oCUYXJlIHRlcm1lZCBhdG9taWMgdmVjdG9ycywgc2luY2UgdGhlaXIgY29tcG9uZW50cyBjYW5ub3QgYmUgYnJva2VuIGRvd24gaW50byBzbWFsbGVyIGNvbXBvbmVudHMuIEluIGNvbnRyYXN0LCBsaXN0cyBhcmUgcmVmZXJyZWQgdG8gYXMgcmVjdXJzaXZlIHZlY3RvcnMuCgoKRm9yIG91ciBmaXJzdCBsb29rIGF0IGxpc3RzLCBsZXTigJlzIGNvbnNpZGVyIGFuIGVtcGxveWVlIGRhdGFiYXNlLiBGb3IgZWFjaCBlbXBsb3llZSwgd2Ugd2lzaCB0byBzdG9yZSB0aGUgbmFtZSwgc2FsYXJ5LCBhbmQgYSBCb29sZWFuIGluZGljYXRpbmcgdW5pb24gbWVtYmVyc2hpcC4gU2luY2Ugd2UgaGF2ZSB0aHJlZSBkaWZmZXJlbnQgbW9kZXMgaGVyZeKAlGNoYXJhY3RlciwgbnVtZXJpYywgYW5kIGxvZ2ljYWwg4oCUIGl04oCZcyBhIHBlcmZlY3QgcGxhY2UgZm9yIHVzaW5nIGxpc3RzLiBPdXIgZW50aXJlIGRhdGFiYXNlIG1pZ2h0IHRoZW4gYmUgYSBsaXN0IG9mIGxpc3RzLCBvciBzb21lIG90aGVyIGtpbmQgb2YgbGlzdCBzdWNoIGFzIGEgZGF0YSBmcmFtZSwgdGhvdWdoIHdlIHdvbuKAmXQgcHVyc3VlIHRoYXQgaGVyZS4gV2UgY291bGQgY3JlYXRlIGEgbGlzdCB0byByZXByZXNlbnQgb3VyIGVtcGxveWVlLCBNYXJjbywgdGhpcyB3YXk6CmBgYHtyfQpqIDwtIGxpc3QobmFtZT0iTWFyY28iLCBzYWxhcnk9NzIwMDAsIHVuaW9uPVQpCmBgYAoKV2UgY291bGQgcHJpbnQgb3V0IGosIGVpdGhlciBpbiBmdWxsIG9yIGJ5IGNvbXBvbmVudDoKClN0YXJ0IGJ5IHByaW50IGogb3V0IGluIGZ1bGwuIFRoaXMgaXMgZG9uZSBieSBqdXN0IGVudGVyaW5nIHRoZSBsaXN0IG5hbWUgajoKCmBgYHtyfQpqCmBgYAoKTm93IHdlIHJldHVybiB0aGUgZGlmZmVyZW50IGxpc3QgZW50cmllcyBpbmRpdmlkdWFsbHkuIFdlIGRvIHRoaXMgaW4gdGhlIHNhbWUgd2F5LCBhcyBpZiB3ZSB3b3VsZCBhY2Nlc3MgYSBjb2x1bW4gb2YgYSBkYXRhIGZyYW1lLCBydW5uaW5nIGxpc3RfbmFtZSRlbnRyeS4KCjEuIFJldHVybiB0aGUgbmFtZSBlbnRyeToKYGBge3J9CmokbmFtZQpgYGAKCjIuIFJldHVybiB0aGUgc2FsYXJ5IGVudHJ5OgpgYGB7cn0KaiRzYWxhcnkKYGBgCgozLiBSZXR1cm4gdGhlIHVuaW9uIGVudHJ5OgpgYGB7cn0KaiR1bmlvbgpgYGAKCgoqKkdlbmVyYWwgTGlzdCBPcGVyYXRpb25zKioKCk5vdyB0aGF0IHlvdeKAmXZlIHNlZW4gYSBzaW1wbGUgZXhhbXBsZSBvZiBjcmVhdGluZyBhIGxpc3QsIGxldOKAmXMgbG9vayBhdCBob3cgdG8gYWNjZXNzIGFuZCB3b3JrIHdpdGggbGlzdHMuCgoqKipMaXN0IEluZGV4aW5nKioqCgpZb3UgY2FuIGFjY2VzcyBhIGxpc3QgY29tcG9uZW50IGluIHNldmVyYWwgZGlmZmVyZW50IHdheXMuIFRoZSBmaXJzdCBtZXRob2QgaXMgdGhlIG9uZSB3ZSBoYXZlIHNlZW4gYWJvdmUuCmBgYHtyfQpqJHNhbGFyeQpgYGAKClRoZSBzZWNvbmQgbWV0aG9kIGlzIHRoZSBzeW50YXggbGlzdF9uYW1lW1siZW50cnkiXV06CmBgYHtyfQpqW1sic2FsYXJ5Il1dCmBgYAoKVGhlIHRoaXJkIHdheSBpcyB1c2luZyB0aGUgaW5kZXggb2YgdGhlIGluZGV4IG9mIHRoZSBlbnRyeSB0aGF0IGlzIHRvIGJlIHJldHVybmVkLiBJbiB0aGlzIGNhc2UsIHNhbGFyeSBpcyB0aGUgc2Vjb25kIGVudHJ5LCBoZW5jZSB3ZSByZXR1cm4gdGhlIGVudHJ5IHdpdGggaW5kZXggMjoKYGBge3J9CmpbWzJdXQpgYGAKCldlIGNhbiByZWZlciB0byBsaXN0IGNvbXBvbmVudHMgYnkgdGhlaXIgbnVtZXJpY2FsIGluZGljZXMsIHRyZWF0aW5nIHRoZSBsaXN0IGFzIGEgdmVjdG9yLiBIb3dldmVyLCBub3RlIHRoYXQgaW4gdGhpcyBjYXNlLCB3ZSB1c2UgZG91YmxlIGJyYWNrZXRzIGluc3RlYWQgb2Ygc2luZ2xlIG9uZXMuIAoKSW4gc3VtbWFyeSwgdGhlcmUgYXJlIHRocmVlIHdheXMgdG8gYWNjZXNzIGFuIGluZGl2aWR1YWwgY29tcG9uZW50IGMgb2YgYSBsaXN0IGxzdCBhbmQgcmV0dXJuIGl0IGluIHRoZSBkYXRhIHR5cGUgb2YgYzogbGlzdF9uYW1lJGVudHJ5LCBsaXN0X25hbWVbW+KAnGVudHJ54oCdXV0sIGFuZCBsaXN0X25hbWVbW2luZGV4XV0uCgoKCioqQWRkaW5nIGFuZCBEZWxldGluZyBMaXN0IEVsZW1lbnRzKioKClRoZSBvcGVyYXRpb25zIG9mIGFkZGluZyBhbmQgZGVsZXRpbmcgbGlzdCBlbGVtZW50cyBhcmlzZSBpbiBhIHN1cnByaXNpbmcgbnVtYmVyIG9mIGNvbnRleHRzLiBUaGlzIGlzIGVzcGVjaWFsbHkgdHJ1ZSBmb3IgZGF0YSBzdHJ1Y3R1cmVzIGluIHdoaWNoIGxpc3RzIGZvcm0gdGhlIGZvdW5kYXRpb24sIHN1Y2ggYXMgZGF0YSBmcmFtZXMgYW5kIFIgY2xhc3Nlcy4KCk5ldyBjb21wb25lbnRzIGNhbiBiZSBhZGRlZCBhZnRlciBhIGxpc3QgaXMgY3JlYXRlZC4KYGBge3J9CnogPC0gbGlzdChmaXJzdD0iY2hhcmFjdGVyIixzZWNvbmQ9NSkKegpgYGAKCldlIGNhbiBhZGQgYW4gYWRkaXRpb25hbCBlbnRyeSBieSBhc3NpZ25pbmcgYSB2YWx1ZSB0byBhIHlldCB1bm5hbWVkIGxpc3QgZW50cnk6CmBgYHtyfQp6JHRoaXJkIDwtICJzb2NjZXIiCnoKYGBgCldlIGNvbmZpcm0gdGhhdCBhIHRoaXJkIGVsZW1lbnQgd2FzIGFkZGVkIHRvIHRoZSBsaXN0IG5hbWVkIHRoaXJkLgoKQWRkaW5nIGNvbXBvbmVudHMgY2FuIGFsc28gYmUgZG9uZSB2aWEgYSB2ZWN0b3IgaW5kZXg6CmBgYHtyfQp6W1s0XV0gPC0gMzIKels1OjddIDwtIGMoRkFMU0UsVFJVRSxUUlVFKQp6CmBgYAoKWW91IGNhbiBhbHNvIGRlbGV0ZSBhIGxpc3QgY29tcG9uZW50IGJ5IHNldHRpbmcgaXQgdG8gTlVMTC4KYGBge3J9Cnokc2Vjb25kIDwtIE5VTEwKegpgYGAKCllvdSBjYW4gYWxzbyBjb25jYXRlbmF0ZSBsaXN0cy4KYGBge3J9CmMobGlzdCgiTHVjYXMiLCA4MzAwMCwgVCksbGlzdCg1KSkKYGBgCgoqKipHZXR0aW5nIHRoZSBTaXplIG9mIGEgTGlzdCoqKgoKU2luY2UgYSBsaXN0IGlzIGEgdmVjdG9yLCB5b3UgY2FuIG9idGFpbiB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgaW4gYSBsaXN0IHZpYSBsZW5ndGgoKS4KYGBge3J9Cmxlbmd0aChqKQpsZW5ndGgoeikKYGBgCgoqKipBY2Nlc3NpbmcgTGlzdCBDb21wb25lbnRzIGFuZCBWYWx1ZXMqKioKCklmIHRoZSBjb21wb25lbnRzIGluIGEgbGlzdCBkbyBoYXZlIHRhZ3MsIGFzIGlzIHRoZSBjYXNlIHdpdGggbmFtZSwgc2FsYXJ5LCBhbmQgdW5pb24gZm9yIGosIHlvdSBjYW4gb2J0YWluIHRoZW0gdmlhIG5hbWVzKCk6CmBgYHtyfQpuYW1lcyhqKQpgYGAKClRvIG9idGFpbiB0aGUgdmFsdWVzLCB1c2UgdW5saXN0KCk6CmBgYHtyfQp1bGogPC0gdW5saXN0KGopCnVsagpgYGAKCldlIGFwcGx5IHRoZSBjbGFzcygpIGZ1bmN0aW9uIHRvIHJldHVybiB0aGUgZGF0YSB0eXBlIG9mIHRoZSBsaXN0OgpgYGB7cn0KY2xhc3ModWxqKQpgYGAKCk9uIHRoZSBvdGhlciBoYW5kLCBpZiBhbGwgdGhlIGNvbXBvbmVudHMgYXJlIG51bWJlcnMsIHdlIHdvdWxkIGdldCBudW1lcmljIGFzIGFuIG91dHB1dC4KYGBge3J9CnogPC0gbGlzdChhPTgsYj0xNixjPTUpCmNsYXNzKHkpCmBgYApXZSBjYW4gYXBwbHkgdGhlIHVubGlzdCgpIGZ1bmN0aW9uLCB0byBub3QgaW50ZXJwcmV0IHRoZSB2YXJpYWJsZSBhcyBhIGxpc3Q6CmBgYHtyfQp5IDwtIHVubGlzdCh6KQp5CmBgYAoKU2FtZSBhcyBhYm92ZSwgd2UgYXBwbHkgdGhlIGNsYXNzKCkgZnVuY3Rpb24gZm9yIHRoZSB1bmxpc3RlZCB5LCBhbmQgd2UgZ2V0IHRoZSBzYW1lIG91dHB1dCBhcyBpZiB3ZSBhcHBseSB0aGUgY2xhc3MoKSBmdW5jdGlvbiB0byB0aGUgbGlzdCB5OgpgYGB7cn0KY2xhc3MoeSkKYGBgCgpTbyB0aGUgb3V0cHV0IG9mIHVubGlzdCgpIGluIHRoaXMgY2FzZSB3YXMgYSBudW1lcmljIHZlY3Rvci4gV2hhdCBhYm91dCBhIG1peGVkIGNhc2U/CmBgYHtyfQp3IDwtIGxpc3QoYT01MixiPSJyYW5kb20gY2hhcmFjdGVyIikKd3UgPC0gdW5saXN0KHcpCmNsYXNzKHd1KQpgYGAKU2luY2UgdGhlcmUgaXMgb25lIGNoYXJhY3RlciBlbGVtZW50IGluIHRoZSBhcnJheSAoInJhbmRvbSBjaGFyYWN0ZXIiKSwgYWxsIGNvbXBvbmVudHMgYXJlIGludGVycHJldGVkIGFzIGNoYXJhY3RlcnMuCgpMZXQgdXMgcHJpbnQgb3V0IHRoZSB1bmxpc3RlZCB3dToKYGBge3J9Cnd1CmBgYApCb3RoIDUyIGFuZCByYW5kb20gY2hhcmFjdGVyIGFyZSBpbnRlcnByZXRlZCBhcyBjaGFyYWN0ZXIgc3RyaW5ncy4KCioqKkFwcGx5aW5nIEZ1bmN0aW9ucyB0byBMaXN0cyoqKgoKVHdvIGZ1bmN0aW9ucyBhcmUgaGFuZHkgZm9yIGFwcGx5aW5nIGZ1bmN0aW9ucyB0byBsaXN0czogbGFwcGx5IGFuZCBzYXBwbHkuCgoqKipVc2luZyB0aGUgbGFwcGx5KCkgYW5kIHNhcHBseSgpIEZ1bmN0aW9ucyoqKgoKVGhlIGZ1bmN0aW9uIGxhcHBseSgpIChmb3IgbGlzdCBhcHBseSkgd29ya3MgbGlrZSB0aGUgbWF0cml4IGFwcGx5KCkgZnVuY3Rpb24sIGNhbGxpbmcgdGhlIHNwZWNpZmllZCBmdW5jdGlvbiBvbiBlYWNoIGNvbXBvbmVudCBvZiBhIGxpc3QgKG9yIHZlY3RvciBjb2VyY2VkIHRvIGEgbGlzdCkgYW5kIHJldHVybmluZyBhbm90aGVyIGxpc3QuIEhlcmXigJlzIGFuIGV4YW1wbGU6CmBgYHtyfQpsYXBwbHkobGlzdCg1OjcsMjU6MzUpLG1lZGlhbikKYGBgClIgYXBwbGllZCBtZWRpYW4oKSB0byA1OjcgYW5kIHRvIDI1OjM1LCByZXR1cm5pbmcgYSBsaXN0IGNvbnNpc3Rpbmcgb2YgNiBhbmQgMzAuIEluIHNvbWUgY2FzZXMsIHN1Y2ggYXMgdGhlIGV4YW1wbGUgaGVyZSwgdGhlIGxpc3QgcmV0dXJuZWQgYnkgbGFwcGx5KCkgY291bGQgYmUgc2ltcGxpZmllZCB0byBhIHZlY3RvciBvciBtYXRyaXguIFRoaXMgaXMgZXhhY3RseSB3aGF0IHNhcHBseSgpIChmb3Igc2ltcGxpZmllZCBbbF1hcHBseSkgZG9lcy4KYGBge3J9CnNhcHBseShsaXN0KDU6NywyNTozNSksbWVkaWFuKQpgYGAKClVzaW5nIHNhcHBseSgpLCByYXRoZXIgdGhhbiBhcHBseWluZyB0aGUgZnVuY3Rpb24gZGlyZWN0bHksIGdhdmUgdXMgdGhlIGRlc2lyZWQgbWF0cml4IGZvcm0gaW4gdGhlIG91dHB1dC4KCgoqKipFeHRlbmRlZCBFeGFtcGxlOiBCYWNrIHRvIHRoZSBBYmFsb25lIERhdGEqKioKCkxldOKAmXMgdXNlIHRoZSBsYXBwbHkoKSBmdW5jdGlvbiBpbiBvdXIgYWJhbG9uZSBnZW5kZXIgZXhhbXBsZS4gUmVjYWxsIHRoYXQgYXQgb25lIHBvaW50IGluIHRoYXQgZXhhbXBsZSwgd2Ugd2lzaGVkIHRvIGtub3cgdGhlIGluZGljZXMgb2YgdGhlIG9ic2VydmF0aW9ucyB0aGF0IHdlcmUgbWFsZSwgZmVtYWxlLCBhbmQgaW5mYW50LiBGb3IgYW4gZWFzeSBkZW1vbnN0cmF0aW9uLCBsZXTigJlzIHVzZSB0aGUgc2FtZSB0ZXN0IGNhc2U6IGEgdmVjdG9yIG9mIGdlbmRlcnMuCmBgYHtyfQpnIDwtIGMoIk0iLCJJIiwiRiIsIkkiLCJNIiwiRiIsIkYiKQpsYXBwbHkoYygiRiIsIk0iLCJJIiksZnVuY3Rpb24oZ2VuZGVyKSB3aGljaChnPT1nZW5kZXIpKQpgYGAKClRoZSBsYXBwbHkoKSBmdW5jdGlvbiBleHBlY3RzIGl0cyBmaXJzdCBhcmd1bWVudCB0byBiZSBhIGxpc3QuIEhlcmUgaXQgd2FzIGEgdmVjdG9yLCBidXQgbGFwcGx5KCkgd2lsbCBjb2VyY2UgdGhhdCB2ZWN0b3IgdG8gYSBsaXN0IGZvcm0uIEFsc28sIGxhcHBseSgpIGV4cGVjdHMgaXRzIHNlY29uZCBhcmd1bWVudCB0byBiZSBhIGZ1bmN0aW9uLiBUaGlzIGNvdWxkIGJlIHRoZSBuYW1lIG9mIGEgZnVuY3Rpb24sIGFzIHlvdSBzYXcgYmVmb3JlLCBvciB0aGUgYWN0dWFsIGNvZGUsIGFzIHdlIGhhdmUgaGVyZS4gVGhpcyBpcyBhbiBhbm9ueW1vdXMgZnVuY3Rpb24sIHdoaWNoIHlvdeKAmWxsIGxlYXJuIG1vcmUgYWJvdXQgaW4gU2VjdGlvbiA3LjEzLgoKVGhlbiBsYXBwbHkoKSBjYWxscyB0aGF0IGFub255bW91cyBmdW5jdGlvbiBvbiDigJxG4oCdLCB0aGVuIG9uIOKAnE3igJ0sIGFuZCB0aGVuIG9uIOKAnEnigJ0uIEluIHRoYXQgZmlyc3QgY2FzZSwgdGhlIGZ1bmN0aW9uIGNhbGN1bGF0ZXMgd2hpY2goZz094oCcRuKAnSksIGdpdmluZyB1cyB0aGUgdmVjdG9yIG9mIGluZGljZXMgaW4gZyBvZiB0aGUgZmVtYWxlcy4gQWZ0ZXIgZGV0ZXJtaW5pbmcgdGhlIGluZGljZXMgZm9yIHRoZSBtYWxlcyBhbmQgaW5mYW50cywgbGFwcGx5KCkgd2lsbCByZXR1cm4gdGhlIHRocmVlIHZlY3RvcnMgaW4gYSBsaXN0LgoKTm90ZSB0aGF0IGV2ZW4gdGhvdWdoIHRoZSBvYmplY3Qgb2Ygb3VyIG1haW4gYXR0ZW50aW9uIGlzIHRoZSB2ZWN0b3IgZyBvZiBnZW5kZXJzLCBpdCBpcyBub3QgdGhlIGZpcnN0IGFyZ3VtZW50IGluIHRoZSBsYXBwbHkoKSBjYWxsIGluIHRoZSBleGFtcGxlLiBJbnN0ZWFkLCB0aGF0IGFyZ3VtZW50IGlzIGFuIGlubm9jdW91cy1sb29raW5nIHZlY3RvciBvZiB0aGUgdGhyZWUgcG9zc2libGUgZ2VuZGVyIGVuY29kaW5ncy4gQnkgY29udHJhc3QsIGcgaXMgbWVudGlvbmVkIG9ubHkgYnJpZWZseSBpbiB0aGUgZnVuY3Rpb24sIGFzIHRoZSBzZWNvbmQgYWN0dWFsIGFyZ3VtZW50LiBUaGlzIGlzIGEgY29tbW9uIHNpdHVhdGlvbiBpbiBSLiBBbiBldmVuIGJldHRlciB3YXkgdG8gZG8gdGhpcyB3aWxsIGJlIHByZXNlbnRlZCBpbiBTZWN0aW9uIDYuMi4yLgoKCioqKlJlY3Vyc2l2ZSBMaXN0cyoqKiAKCkxpc3RzIGNhbiBiZSByZWN1cnNpdmUsIG1lYW5pbmcgdGhhdCB5b3UgY2FuIGhhdmUgbGlzdHMgd2l0aGluIGxpc3RzLiBIZXJl4oCZcyBhbiBleGFtcGxlOgpgYGB7cn0KYiA8LSBsaXN0KHUgPSA1LCB2ID0gMTIpCmMgPC0gbGlzdCh3ID0gMTMpCmEgPC0gbGlzdChiLGMpCmBgYApUaGUgbGlzdCBiIGhhcyB0d28gZW50cmllcywgdGhlIGxpc3QgYyBoYXMgb25lIGVudHJ5LiBhIHRoZW4gY29tYmluZXMgbGlzdHMgYiBhbmQgYyBpbiBhIG5ldyBsaXN0IG9mIGxpc3RzLiBMZXQgdXMgc2VlIHdoYXQgdGhpcyBsb29rcyBsaWtlIHdoZW4gd2UgcmV0dXJuIGl0OgpgYGB7cn0KYQpgYGAKVGhlIHR3byBsaXN0cyBiIChbWzFdXSkgYW5kIGMoW1syXV0pIGFyZSByZXR1cm5lZCwgd2hlcmUgYiBoYXMgdHdvIGNvbXBvbmVudHMuIExldCB1cyBwcmludCB0aGUgbGVuZ3RoIG9mIGE6CmBgYHtyfQpsZW5ndGgoYSkKYGBgClRoZSBsZW5ndGggb2YgYSBpcyAyLiBUaGlzIGlzIGJlY2F1c2UgYSBjb250YWlucyAyIGxpc3RzLgoKVGhlIGNvZGUgbWFrZXMgYSBpbnRvIGEgdHdvLWNvbXBvbmVudCBsaXN0LCB3aXRoIGVhY2ggY29tcG9uZW50IGl0c2VsZiBhbHNvIGJlaW5nIGEgbGlzdC4gVGhlIGNvbmNhdGVuYXRlIGZ1bmN0aW9uIGMoKSBoYXMgYW4gb3B0aW9uYWwgYXJndW1lbnQgcmVjdXJzaXZlLCB3aGljaCBjb250cm9scyB3aGV0aGVyIGZsYXR0ZW5pbmcgb2NjdXJzIHdoZW4gcmVjdXJzaXZlIGxpc3RzIGFyZSBjb21iaW5lZC4KCk5vdyBsZXQgdXMgY3JlYXRlIGEgbGlzdCBwIHdpdGggMyBlbnRyaWVzLCB3aGVyZSBvbmUgY29tcG9uZW50IGlzIGEgbGlzdCBpdHNlbGY6CmBgYHtyfQpwIDwtIGMobGlzdChhPTQsYj0xLGM9bGlzdChkPTI1LGU9NykpKQpwCmBgYApUaGUgbGVuZ3RoIG9mIHAgaXMgMywgc2luY2UgcCBoYXMgdGhyZWUgZW50cmllczoKYGBge3J9Cmxlbmd0aChwKQpgYGAKSG93ZXZlciwgaWYgd2Ugc2V0IHRoZSBvcHRpb25hbCBwYXJhbWV0ZXIgcmVjdXJzaXZlIHRvIFRSVUUsIG91ciBsaXN0IGhhcyA0IGNvbXBvbmVudHMuCmBgYHtyfQpwMiA9IGMobGlzdChhPTQsYj0xLGM9bGlzdChkPTI1LGU9NykpLHJlY3Vyc2l2ZT1UKQpwMgpgYGAKV2UgY29uZmlybSB0aGlzIGJ5IGFwcGx5aW5nIHRoZSBsZW5ndGgoKSBmdW5jdGlvbiBhZ2FpbjoKYGBge3J9Cmxlbmd0aChwMikKYGBgCgpJbiB0aGUgZmlyc3QgY2FzZSwgd2UgYWNjZXB0ZWQgdGhlIGRlZmF1bHQgdmFsdWUgb2YgcmVjdXJzaXZlLCB3aGljaCBpcyBGQUxTRSwgYW5kIG9idGFpbmVkIGEgcmVjdXJzaXZlIGxpc3QsIHdpdGggdGhlIGMgY29tcG9uZW50IG9mIHRoZSBtYWluIGxpc3QgaXRzZWxmIGJlaW5nIGFub3RoZXIgbGlzdC4gSW4gdGhlIHNlY29uZCBjYWxsLCB3aXRoIHJlY3Vyc2l2ZSBzZXQgdG8gVFJVRSwgd2UgZ290IGEgc2luZ2xlIGxpc3QgYXMgYSByZXN1bHQ7IG9ubHkgdGhlIG5hbWVzIGxvb2sgcmVjdXJzaXZlLiAoSXTigJlzIG9kZCB0aGF0IHNldHRpbmcgcmVjdXJzaXZlIHRvIFRSVUUgZ2l2ZXMgYSBub25yZWN1cnNpdmUgbGlzdC4pIFJlY2FsbCB0aGF0IG91ciBmaXJzdCBleGFtcGxlIG9mIGxpc3RzIGNvbnNpc3RlZCBvZiBhbiBlbXBsb3llZSBkYXRhYmFzZS4gSSBtZW50aW9uZWQgdGhhdCBzaW5jZSBlYWNoIGVtcGxveWVlIHdhcyByZXByZXNlbnRlZCBhcyBhIGxpc3QsIHRoZSBlbnRpcmUgZGF0YWJhc2Ugd291bGQgYmUgYSBsaXN0IG9mIGxpc3RzLiBUaGF0IGlzIGEgY29uY3JldGUgZXhhbXBsZSBvZiByZWN1cnNpdmUgbGlzdHMu