# File src/library/base/R/match.R # Part of the R package, https://www.R-project.org # # Copyright (C) 1995-2025 The R Core Team # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # A copy of the GNU General Public License is available at # https://www.R-project.org/Licenses/ match <- function(x, table, nomatch = NA_integer_, incomparables = NULL) .Internal(match(x, table, nomatch, incomparables)) match.call <- function(definition=sys.function(sys.parent()), call=sys.call(sys.parent()), expand.dots=TRUE, envir=parent.frame(2L)) { if (!missing(definition) && is.null(definition)) { definition <- sys.function(sys.parent()) } .Internal(match.call(definition,call,expand.dots,envir)) } pmatch <- function(x, table, nomatch = NA_integer_, duplicates.ok = FALSE) .Internal(pmatch(as.character(x), as.character(table), nomatch, duplicates.ok)) # "utils::hasName(x, name)" is defined to be the same as "name %in% names(x)", # so change it if this changes. `%in%` <- function(x, table) match(x, table, nomatch = 0L) > 0L `%notin%` <- function(x, table) match(x, table, nomatch = 0L) == 0L match.arg <- function (arg, choices, several.ok = FALSE) { if (missing(choices)) { formal.args <- formals(sys.function(sysP <- sys.parent())) choices <- eval(formal.args[[as.character(substitute(arg))]], envir = sys.frame(sysP)) } if (is.null(arg)) return(choices[1L]) else if(!is.character(arg)) stop("'arg' must be NULL or a character vector") all.match <- FALSE if(!is.logical(several.ok)) { if(is.character(several.ok) && startsWith(several.ok, "all")) several.ok <- all.match <- TRUE else stop("'several.ok' must be logical or a string starting with \"all\"") } else if (!several.ok) { # most important (default) case: ## the arg can be the whole of choices as a default argument. if(identical(arg, choices)) return(arg[1L]) if(length(arg) != 1L) stop(gettextf("'%s' must be of length 1", "arg"), domain=NA) } else if(length(arg) == 0L) stop("'arg' must be of length >= 1") ## handle each element of arg separately i <- pmatch(arg, choices, nomatch = 0L, duplicates.ok = TRUE) if(all(i0 <- i == 0L) || (all.match && any(i0))) stop(sprintf(ngettext(length(chs <- unique(choices[nzchar(choices)])), "'arg' should be %s", "'arg' should be one of %s"), paste(dQuote(chs), collapse=", ")), domain = NA) choices[i[i > 0L]] } charmatch <- function(x, table, nomatch = NA_integer_) .Internal(charmatch(as.character(x), as.character(table), nomatch)) char.expand <- function(input, target, nomatch = stop("no match")) { if(length(input) != 1L) stop("'input' must have length 1") if(!(is.character(input) && is.character(target))) stop("'input' and 'target' must be character vectors") y <- .Internal(charmatch(input, target, NA_integer_)) if(anyNA(y)) eval(nomatch) target[y] } mtfrm <- function(x) UseMethod("mtfrm") mtfrm.default <- function(x) { if(length(y <- as.character(x)) != length(x)) stop("cannot mtfrm") y } mtfrm.Date <- # <- for speed mtfrm.POSIXct <- mtfrm.POSIXlt <- function(x) as.vector(x, "any")