我很难理解为什么==
和%in%
在应用于依赖于字符向量时会产生不同结果的原因,而这些字符向量似乎只依赖于向量'编码。一个例子:
a <- 'Köln'
Encoding(a) <- 'unknown'
Encoding(a)
# [1] "unknown"
b <- a
Encoding(b) <- 'UTF-8'
a == b
# [1] TRUE
a %in% b
# [1] FALSE
更新:
结果似乎也与平台有关。这两个陈述回归:
TRUE
和FALSE
FALSE
和FALSE
TRUE
和TRUE
我开始认为这是一个错误。
答案 0 :(得分:3)
这确实是一个错误,它是fixed in 3.3.1。
这个行为实际上比你的例子所表示的更奇怪,因为当你在FALSE
的左侧有一个元素时,你才会得到%in%
:
> a %in% b
[1] FALSE
> c(a, a) %in% b
[1] TRUE TRUE
正如评论所暗示的,%in%
只是致电match
,因此也可以看到问题:
> match(a, b)
[1] NA
> match(c(a, a), b)
[1] 1 1
%in%
和match
的重要论据是x
和table
,其中任一函数都会在x
中搜索table
。在引擎盖下,R在match5
中定义的unique.c
函数中执行此操作。如果您有多个x
,match5
将从table
创建一个哈希表,以启用快速查找。如果你仔细研究代码,你会发现比较是在一个名为sequal
的函数中完成的,它返回Seql(STRING_ELT(x, i), STRING_ELT(y, j))
(好吧,它实际上比这个更复杂*)。然后,如果您查看Seql
中的memory.c
,您会发现:
int result = !strcmp(translateCharUTF8(a), translateCharUTF8(b));
如您所见,将字符串转换为UTF-8。
但是,如果x
只有一个元素,那么在创建哈希表时遇到麻烦是很愚蠢的,因为我们可以只扫描table
一次,看看x
是否是那里。在3.3.0中,检查x
与table
的每个元素之间的相等性的代码未使用Seql
,并且未将字符串转换为UTF-8。但是从3.3.1开始,使用Seql
,因此行为是固定的。
*关于字符串相等的一点:R实际上会缓存字符串,因此它不需要存储一堆副本。因此,如果两个字符串位于同一位置,它们是相同的,无需进一步检查!
> .Internal(inspect("Köln"))
@10321b758 16 STRSXP g0c1 [NAM(2)] (len=1, tl=0)
@106831eb8 09 CHARSXP g1c1 [MARK,gp=0x28,ATT] [UTF8] [cached] "Köln"
> .Internal(inspect(b))
@106831cd8 16 STRSXP g1c1 [MARK,NAM(2)] (len=1, tl=0)
@106831eb8 09 CHARSXP g1c1 [MARK,gp=0x28,ATT] [UTF8] [cached] "Köln"