2016-06-08 37 views
15

我很難理解爲什麼==%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 

更新

看來結果還依賴於平臺的。兩個語句返回:

  • R上3.3.0 TRUEFALSE在OS X 10.11.5
  • FALSEFALSE R上3.3.0在Windows 10(64位)上
  • TRUETRUE R 3.2.3在CentOS 7上

我開始認爲這是一個錯誤。

+1

'在%C(A,B)'爲真'Encoding'一個% - ?'的比賽,pmatch,charmatch,複製和獨特的所有匹配以UTF-8如果任何元素被標記爲UTF-8「。 – rawr

+0

== =='的文檔說在比較之前字符都轉換爲UTF-8 ...我會好奇爲什麼不同的行爲。 – joran

+1

@rawr嗯,但'a'在'c(a)'中,所以它也在'c(a,b)'中。但爲什麼'c(a)'中不是'b'? '%in%'不檢查變量名是否相同,只有值,我不明白爲什麼這些值不相同,因爲'=='返回'TRUE'。 – RoyalTS

回答

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%matchxtable,其中任一函數都在table中搜索x。在引擎蓋下,R在unique.c中定義的match5函數中執行此操作。如果您有多個x,match5將從table創建一個哈希表以啓用快速查找。如果你仔細查看代碼,你會發現比較是在一個名爲sequal的函數中完成的,該函數返回Seql(STRING_ELT(x, i), STRING_ELT(y, j))(好吧,實際上它比這個*更復雜一點)。然後,如果你去看看Seqlmemory.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" 
相關問題