Skip to content

Commit 7101184

Browse files
author
maechler
committed
mv & unhide %notin% from {tools} to {base}
git-svn-id: https://svn.r-project.org/R/trunk@89099 00db46b3-68df-0310-9c12-caf00c1e9a41
1 parent 8834698 commit 7101184

File tree

4 files changed

+38
-24
lines changed

4 files changed

+38
-24
lines changed

doc/NEWS.Rd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@
141141
\code{tools::Rd2txt_options(descStyle=NULL)} to get the old
142142
behaviour with a simple space; a \code{"colon"} variant is also
143143
available.
144+
145+
\item \code{x \%notin\% table} newly in \pkg{base} is an idiom
146+
for \code{!(x \%in\% table)} and provided almost entirely for
147+
convenience and code readability, from an R-devel suggestion, after
148+
many years of private definitions mostly hidden in packages,
149+
including in \R's \pkg{tools} package.
144150
}
145151
}
146152

src/library/base/R/match.R

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ pmatch <- function(x, table, nomatch = NA_integer_, duplicates.ok = FALSE)
3636

3737
# "utils::hasName(x, name)" is defined to be the same as "name %in% names(x)",
3838
# so change it if this changes.
39-
`%in%` <- function(x, table) match(x, table, nomatch = 0L) > 0L
39+
`%in%` <- function(x, table) match(x, table, nomatch = 0L) > 0L
40+
`%notin%` <- function(x, table) match(x, table, nomatch = 0L) == 0L
4041

4142
match.arg <- function (arg, choices, several.ok = FALSE)
4243
{

src/library/base/man/match.Rd

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,23 @@
44
% Distributed under GPL 2 or later
55

66
\name{match}
7+
\title{Value Matching}
78
\alias{match}
89
\alias{\%in\%}
9-
\title{Value Matching}
10+
\alias{\%notin\%}
1011
\description{
1112
\code{match} returns a vector of the positions of (first) matches of
1213
its first argument in its second.
1314

14-
\code{\%in\%} is a more intuitive interface as a binary operator,
15-
which returns a logical vector indicating if there is a match or not
15+
\code{\%in\%} and \code{\%notin\%} are more intuitive interfaces as binary operators,
16+
returning a logical vector indicating if there is a match or not
1617
for its left operand.
1718
}
1819
\usage{
1920
match(x, table, nomatch = NA_integer_, incomparables = NULL)
2021

21-
x \%in\% table
22+
x \%in\% table
23+
x \%notin\% table
2224
}
2325
\arguments{
2426
\item{x}{vector or \code{NULL}: the values to be matched.
@@ -35,21 +37,30 @@ x \%in\% table
3537
\value{
3638
A vector of the same length as \code{x}.
3739

38-
\code{match}: An integer vector giving the position in \code{table} of
40+
\describe{
41+
\item{\code{match}:}{An integer vector giving the position in \code{table} of
3942
the first match if there is a match, otherwise \code{nomatch}.
4043

4144
If \code{x[i]} is found to equal \code{table[j]} then the value
4245
returned in the \code{i}-th position of the return value is \code{j},
4346
for the smallest possible \code{j}. If no match is found, the value
4447
is \code{nomatch}.
45-
46-
\code{\%in\%}: A logical vector, indicating if a match was located for
47-
each element of \code{x}: thus the values are \code{TRUE} or
48-
\code{FALSE} and never \code{NA}.
48+
}
49+
\item{\code{\%in\%}:}{A logical vector, indicating if a match was located for
50+
each element of \code{x}: thus the values are \code{TRUE} or
51+
\code{FALSE} and never \code{NA}.}
52+
53+
\item{\code{\%notin\%}:}{A logical vector, simply the negation of the
54+
corresponding \code{\%in\%} call.}
55+
}
4956
}
5057
\details{
5158
\code{\%in\%} is currently defined as \cr
52-
\code{"\%in\%" <- function(x, table) match(x, table, nomatch = 0) > 0}
59+
\code{`\%in\%` <- function(x, table) match(x, table, nomatch = 0L) > 0L}
60+
61+
\code{\%notin\%} could succinctly be defined as \code{\link{Negate}(`\%in\%`)},
62+
but for symmetry and efficiency is \cr
63+
\code{`\%notin\%` <- function(x, table) match(x, table, nomatch = 0L) == 0L}
5364

5465
Factors, raw vectors and lists are converted to character vectors,
5566
internally classed objects are transformed via \code{\link{mtfrm}}, and
@@ -79,7 +90,8 @@ x \%in\% table
7990
in different encodings but would agree when translated to UTF-8 (see
8091
\code{\link{Encoding}}).
8192
82-
That \code{\%in\%} never returns \code{NA} makes it particularly
93+
That \code{\%in\%} and \code{\%notin\%} never return \code{NA} makes them
94+
particularly
8395
useful in \code{if} conditions.
8496
}
8597
\references{
@@ -107,16 +119,16 @@ x \%in\% table
107119
intersect # the R function in base is slightly more careful
108120
intersect(1:10, 7:20)
109121
110-
1:10 \%in\% c(1,3,5,9)
122+
1:10 \%in\% c(1,3,5,9) %
111123
sstr <- c("c","ab","B","bba","c",NA,"@","bla","a","Ba","\%")
112-
sstr[sstr \%in\% c(letters, LETTERS)]
124+
sstr[sstr \%in\% c(letters, LETTERS)] %
113125
114-
"\%w/o\%" <- function(x, y) x[!x \%in\% y] #-- x without y
115-
(1:10) \%w/o\% c(3,7,12)
126+
"\%w/o\%" <- function(x, y) x[x \%notin\% y] #-- x without y
127+
(1:10) \%w/o\% c(3,7,12) %
116128
## Note that setdiff() is very similar and typically makes more sense:
117129
c(1:6,7:2) \%w/o\% c(3,7,12) # -> keeps duplicates
118130
setdiff(c(1:6,7:2), c(3,7,12)) # -> unique values
119-
131+
%
120132
## Illuminating example about NA matching in complex values
121133
r <- c(1, NA, NaN)
122134
zN <- c(complex(real = NA , imaginary = r ),

src/library/tools/R/utils.R

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -593,18 +593,13 @@ filtergrep <-
593593
function(pattern, x, ...)
594594
grep(pattern, x, invert = TRUE, value = TRUE, ...)
595595

596-
### ** %notin%
597-
598-
`%notin%` <-
599-
function(x, y)
600-
is.na(match(x, y))
601596

602597
### ** %w/o%
603598

604599
## x without y, as in the examples of ?match.
605600
`%w/o%` <-
606601
function(x, y)
607-
x[is.na(match(x, y))]
602+
x[x %notin% y]
608603

609604
### ** .OStype
610605

@@ -903,7 +898,7 @@ function(funnames, pkgnames = character(), colons = c("::", ":::"))
903898
## Use pkgnames = NA_character_ to match *any* PKG::FUN call with
904899
## FUN in funnames. Strange but why not? Or better to use "*"?
905900
function(e) {
906-
(is.call(e) &&
901+
(is.call(e) &&
907902
((is.name(x <- e[[1L]]) &&
908903
as.character(x) %in% funnames)) ||
909904
((is.call(x <- e[[1L]]) &&

0 commit comments

Comments
 (0)