2014-02-13 2 views
0

Есть ли способ добиться частичного согласования в атомных векторах? Я знаю, что оператор $ не работает с атомными векторами, но я думал, что это возможно, используя [["i", exact = FALSE]].Частичное согласование в атомных векторах

x <- c("a1", "a2", "a3", "b1", "b2") 
names(x) <- x 

x$a 

просто возвращает "$ оператор недопустим для атомных векторов"

x[["a", exact=FALSE]] 

возвращает "Object "а" не найден".

Есть ли способ сделать частичное согласование с атомными векторами?

Cheers, Zuup

ответ

2

Я не знаю, о чем-то, что делает именно то, что вы хотите. Ниже немного запутанно, но может работать для вас:

x[grep("^a", names(x))] 
# a1 a2 a3 
# "a1" "a2" "a3" 

Кроме того, частичное соответствие может быть сделано, но он работает только тогда, когда есть только один элемент индекса, который соответствует вашему частичному индексу. Так, например:

y <- 1:5 
names(y) <- paste(letters[1:5], 1:5) 
y[["a", exact=F]] 
# [1] 1 
names(y)[[2]] <- "a 2" # add a second index that starts with "a" 
y[["a", exact=F]] 
# Error in y[["a", exact = F]] : subscript out of bounds 

Наконец, обратите внимание, что вам нужно процитировать строку символов внутри [[, которые вы не делали в вашем примере.

+0

Удивительная команда «grep» - это именно то, что я искал. Можно даже выполнить поиск внутри самого вектора без необходимости назначения содержимого в качестве имен. – Zuup

1

В принципе, благодаря перегрузке операторов вы можете получить любое поведение, которое хотите. С помощью следующего кода скобки перегружены, чтобы вести себя так, как вы хотите, чтобы вести себя:

# overload the brackets for reading out 
"[.pmatch_vec" = function(obj,idx){ 
    origclass <- setdiff(class(obj),"pmatch_vec") 
    if (length(origclass)==0) origclass <- "" 
    class(obj) <- origclass 
    if (!is.character(idx)) 
    return(obj[idx]) 
    else 
    return(obj[grep(paste("^",idx,sep=""),names(obj))]) 
} 

# overload the assignment operator []<- 
"[<-.pmatch_vec" = function(obj,idx,value){ 
    saveclass <- class(obj) 
    origclass <- setdiff(class(obj),"pmatch_vec") 
    if (length(origclass)==0) origclass <- "" 
    class(obj) <- origclass 
    if (!is.character(idx)) 
    obj[idx] <- value 
    else 
    obj[grep(paste("^",idx,sep=""),names(obj))] <- value 
    class(obj) <- saveclass 
    return(obj) 
} 

Поскольку это опасно перегружать скобки в общем, они были перегруженный только для определенного класса «pmatch_vec». Кроме того, обратите внимание, что в рамках этих функций «pmatch_vec» временно удаляется из атрибута класса, чтобы избежать бесконечной рекурсии.

Вот некоторые примеры поведения атомных векторов, определяемое как класс «pmatch_vec»:

# create some vector 
A = 1:6 
names(A) <- c(paste("a",1:3,sep=""),paste("b",1:3,sep="")) 
# set the class 
class(A) = c("pmatch_vec") 

# some demonstraton 
A["a"] 
# a1 a2 a3 
# 1 2 3 

A["b"] 
# b1 b2 b3 
# 4 5 6 

A["b"] <- 7 
A 
# a1 a2 a3 b1 b2 b3 
# 1 2 3 7 7 7 

Если вектор, используемый для индексации не символьный типа, класс «pmatch_vec» ведет себя, как если бы это обычный атомный вектор:

A[1:2] <- 8 
A[1:4] 
# a1 a2 a3 b1 
# 8 8 3 7 
+0

Спасибо за ваш ответ! Я не знал, что так легко сгибать код так, как вы хотите, перегружая. В моем случае это немного проблематично, потому что он должен работать в рамках пакета, и я немного осторожен с представлением перегруженных общих операторов вроде этого! Но я буду держать ваш совет в виду, что я достигаю другой проблемы, которую я не могу обойти с помощью обычного кода :) – Zuup

Смежные вопросы