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.

  1. Return the name entry:
j$name
[1] "Marco"
  1. Return the salary entry:
j$salary
[1] 72000
  1. 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