hi, i have two questions: (1) lookup: given a list of 'strings' in a list, i want to know the index of a given string in the list. if the string is not in the list, the index can be 0 or length()+1. for example, suppose i have names <- c("dog", "cat", "pig", "fish"); then i want lookup(names, "cat") to return 2 and lookup(names, "ant") to return 0 (or 5) i am currently doing this in a for loop with a break using identical(). however, since i call this function repeatedly, i am wondering whether there is a more efficient way of doing this. (2) combining lists: when lists are combined, the higher level list structure appears to be lost. what i mean is, suppose i have two lists with the same structure a <- list(name="foo", year=1989, grade="A"); b <- list(name="bar", year=2000, grade="B+"); then when i combine the two lists into one ab <- c(a, b); length(ab) returns length(a)+length(b), not 2. given a list of lists, is there any way i can loop through each list and work with the named components in each list? it seems that i need to know the length of each list and the order each component appears in the list to work with the combined list. the solution i am currently using is not to combine the list but use ... in a function argument and to extract each list by: foo <- function(...) { args <- list(...); for (i in 1:length(args)) { #extract i-th list tmp <- args[[i]]; } } h. -------------------------------------------------------------------- Time series regression studies give no sign of converging toward the truth. (Phillip Cagan)
Three quick answers: (1) function match("cat", names, 0) would return 2. (2) syntax list(a,b) would return a list of lists with length 2. (3) syntax unlist(lapply(ab, function(x) x[["year"]])) would return a vector equal to c(1989,2000). See the interactive help for each of these functions. - tom blackwell - u michigan medical school - ann arbor - On Wed, 19 Feb 2003, Hiroyuki Kawakatsu wrote:> hi, > > i have two questions: > (1) lookup: given a list of 'strings' in a list, i want to know the index > of a given string in the list. if the string is not in the list, the index > can be 0 or length()+1. for example, suppose i have > names <- c("dog", "cat", "pig", "fish"); > then i want > lookup(names, "cat") to return 2 and > lookup(names, "ant") to return 0 (or 5) > > i am currently doing this in a for loop with a break using identical(). > however, since i call this function repeatedly, i am wondering whether > there is a more efficient way of doing this. > > (2) combining lists: when lists are combined, the higher level list > structure appears to be lost. what i mean is, suppose i have two lists > with the same structure > a <- list(name="foo", year=1989, grade="A"); > b <- list(name="bar", year=2000, grade="B+"); > then when i combine the two lists into one > ab <- c(a, b); > length(ab) returns length(a)+length(b), not 2. > > given a list of lists, is there any way i can loop through each > list and work with the named components in each list? it seems that i need > to know the length of each list and the order each component appears in > the list to work with the combined list. the solution i am currently using > is not to combine the list but use ... in a function argument and to > extract each list by: > > foo <- function(...) { > args <- list(...); > for (i in 1:length(args)) { > #extract i-th list > tmp <- args[[i]]; > } > } > > h. > -------------------------------------------------------------------- > Time series regression studies give no sign of converging toward the > truth. (Phillip Cagan) > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > http://www.stat.math.ethz.ch/mailman/listinfo/r-help >
On 19 Feb 2003 at 6:46, Hiroyuki Kawakatsu wrote: Is this what you want:> names <- c("dog",+ "cat", "pig", "fish");> names[1] "dog" "cat" "pig" "fish"> which(names=="cat")[1] 2> which(names=="ant")numeric(0)> lookup <- function(db, item) {+ res <- which(db==item) + if (length(res)==0) res <- 0 + res}> lookup(names, "cat")[1] 2> lookup(names, "ant")[1] 0> hi, > > i have two questions: > (1) lookup: given a list of 'strings' in a list, i want to know the index > of a given string in the list. if the string is not in the list, the index > can be 0 or length()+1. for example, suppose i have > names <- c("dog", "cat", "pig", "fish"); > then i want > lookup(names, "cat") to return 2 and > lookup(names, "ant") to return 0 (or 5) > > i am currently doing this in a for loop with a break using identical(). > however, since i call this function repeatedly, i am wondering whether > there is a more efficient way of doing this. > > (2) combining lists: when lists are combined, the higher level list > structure appears to be lost. what i mean is, suppose i have two lists > with the same structure > a <- list(name="foo", year=1989, grade="A"); > b <- list(name="bar", year=2000, grade="B+"); > then when i combine the two lists into one > ab <- c(a, b); > length(ab) returns length(a)+length(b), not 2.so you want ab <- list(a,b)> > given a list of lists, is there any way i can loop through each > list and work with the named components in each list? it seems that i need > to know the length of each list and the order each component appears in > the list to work with the combined list. the solution i am currently using > is not to combine the list but use ... in a function argument and to > extract each list by: > > foo <- function(...) { > args <- list(...); > for (i in 1:length(args)) { > #extract i-th list > tmp <- args[[i]]; > } > } > > h. > -------------------------------------------------------------------- > Time series regression studies give no sign of converging toward the > truth. (Phillip Cagan) > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > http://www.stat.math.ethz.ch/mailman/listinfo/r-help
On Wed, Feb 19, 2003 at 06:46:28AM -0800, Hiroyuki Kawakatsu wrote:> hi, > > i have two questions:I counted three ;-)> (1) lookup: given a list of 'strings' in a list, i want to know the index > of a given string in the list. if the string is not in the list, the index > can be 0 or length()+1. for example, suppose i have > names <- c("dog", "cat", "pig", "fish"); > then i want > lookup(names, "cat") to return 2 and > lookup(names, "ant") to return 0 (or 5)That's not a list of strings; it's a character-type vector. See below for more. For this, grep() is your friend. To match a word exactly, you need to put the pattern between a ^ and a $, all in quotes. If you don't, you'll get all partial matches too (which is also pretty useful sometimes). eg:> names <- c("dog", "cat", "pig", "fish","catskills","cat stevens") > grep("^cat$",names)[1] 2> grep("cat",names)[1] 2 5 6 (I'm told that now works on all platforms - thanks for the regexes, R-core!)> (2) combining lists: when lists are combined, the higher level list > structure appears to be lost. what i mean is, suppose i have two lists > with the same structure > a <- list(name="foo", year=1989, grade="A"); > b <- list(name="bar", year=2000, grade="B+"); > then when i combine the two lists into one > ab <- c(a, b); > length(ab) returns length(a)+length(b), not 2.c() makes vectors. list() makes lists. Vectors: each element is of the *same* data type (numeric, character, Date/Time, factor, logical,...). This is why you lose the list-like character above; you've "pushed" everything into a character vector. This is a handy way of throwing away exotic data classes, btw. I think what you wanted to do was: ab <- list(a, b) length(ab) ab> given a list of lists, is there any way i can loop through each > list and work with the named components in each list?lapply() is your friend, and can help with recursion too. lapply(your.big.list,function(bar,...) { listfunc <- function(foo,...) { #magic thing you do to non-list elements; #you didn't specify, so I'm not sure what you want. } if(is.list(bar)) lapply(bar,listfunc) else listfunc(bar,...) } This can make life easy, but think really hard about what you want the functions to do, and what values you want them to return, and how you're going to structure this. Generalised list travels aren't trivial, particularly the return trip. Hope that helps Jason -- Indigo Industrial Controls Ltd. 64-21-343-545 jasont at indigoindustrial.co.nz