==和%in%根据字符编码而不同?

时间:2016-06-08 20:50:45

标签: 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

更新

结果似乎也与平台有关。这两个陈述回归:

    在操作系统X 10.11.5的R 3.3.0上
  • TRUEFALSE
  • Windows 10(64位)上的R 3.3.0上的
  • FALSEFALSE
  • 在CentOS 7的R 3.2.3上
  • TRUETRUE

我开始认为这是一个错误。

1 个答案:

答案 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的重要论据是xtable,其中任一函数都会在x中搜索table。在引擎盖下,R在match5中定义的unique.c函数中执行此操作。如果您有多个xmatch5将从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中,检查xtable的每个元素之间的相等性的代码未使用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"