R ==和%在%中根据字符编码不同?

R ==和%在%中根据字符编码不同?,r,character-encoding,R,Character Encoding,我很难理解为什么%中的==和%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 a这确实是一个bug,而且确实是 该行为实际上比您的示例显示的更为奇怪,因为只有当%中%的左侧有一个元素时

我很难理解为什么%中的
==
%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

a这确实是一个bug,而且确实是

该行为实际上比您的示例显示的更为奇怪,因为只有当%
%的左侧有一个元素时,才会得到
FALSE

> a %in% b
[1] FALSE
> c(a, a) %in% b
[1] TRUE TRUE
正如注释所暗示的,%
中的
%只调用
match
,因此问题也可以在那里看到:

> match(a, b)
[1] NA
> match(c(a, a), b)
[1] 1 1
%
match
%的重要参数是
x
table
,其中任一函数在
table
中搜索
x
。在发动机罩下,R在
unique.c
中定义的
match5
功能中执行此操作。如果您有多个
x
match5
将从
创建一个哈希表,以启用快速查找。如果你仔细研究代码,你会发现比较是在一个名为
sequal
的函数中完成的,该函数返回
Seql(STRING_ELT(x,i),STRING_ELT(y,j))
(实际上,它比这个函数复杂一点)。然后,如果您查看
memory.c
中的
Seql
,您会发现:

int result = !strcmp(translateCharUTF8(a), translateCharUTF8(b));
如您所见,它将字符串转换为UTF-8

然而,如果
x
只有一个元素,那么创建一个哈希表是很愚蠢的,因为我们可以只扫描
table
一次,看看
x
是否存在。在3.3.0中,用于检查
x
表的每个元素之间是否相等的代码没有使用
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"

%c(a,b)
中的
a%为真
?编码--
匹配,pmatch,charmatch,如果有任何元素被标记为UTF-8,则重复且唯一的所有元素在UTF-8中都匹配。
=
的文档中说,在比较之前,字符都转换为UTF-8……我很好奇为什么会有不同的行为。@rawr是的,但是
a
c(a)
中,所以它也在
c(a,b)
中。但是为什么
b
不在
c(a)
中呢<%
中的code>%不检查变量名是否相同,只检查值,我不理解为什么值不相同,因为
=
返回
TRUE
match
的文档说“如果任何输入标记为“bytes”,字符串将作为字节序列进行比较。”。
未知
是字节序列吗。。。在我的Cygwin 3.1.3安装中,两个测试的结果都是
TRUE
,但在我的RStudio 3.2.1安装中,两个测试的结果都是
FALSE
。而你(OP)似乎得到了一种混合物。没有什么是有意义的。。。没有什么是有意义的。。。