2016-06-08 15 views
15

Tôi đang gặp khó khăn khi hiểu tại sao ==%in% sẽ tạo ra các kết quả khác nhau khi áp dụng cho các vectơ ký tự phụ thuộc, dường như chỉ trên mã hóa vectơ. Một ví dụ:== và% trong% khác nhau dựa trên mã hóa ký tự?

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 

Cập nhật:

Có vẻ kết quả cũng là nền tảng phụ thuộc. Hai báo cáo trở lại:

  • TRUEFALSE vào R 3.3.0 trên OS X 10.11.5
  • FALSEFALSE vào R 3.3.0 trên Windows 10 (64 bit)
  • TRUETRUE trên R 3.2.3 trên CentOS 7

Tôi bắt đầu nghĩ đây là lỗi.

+1

'a% trong% c (a, b)' là true '? Encoding' -' match, pmatch, charmatch, trùng lặp và duy nhất tất cả khớp trong UTF-8 nếu bất kỳ phần tử nào được đánh dấu là UTF-8.' – rawr

+0

Và tài liệu cho '==' nói rằng các ký tự đều được chuyển đổi thành UTF-8 trước khi so sánh ... Tôi sẽ tò mò tại sao lại có hành vi khác. – joran

+1

@rawr Vâng vâng, nhưng 'a' nằm trong' c (a) 'vì vậy nó cũng trong' c (a, b) '. Nhưng tại sao không phải là 'b' trong' c (a) '? '% in%' không kiểm tra tên biến là giống hệt nhau, chỉ có giá trị và tôi không hiểu tại sao các giá trị không giống nhau khi '==' trả về 'TRUE'. – RoyalTS

Trả lời

3

Đó thực sự là lỗi và là fixed in 3.3.1.

Các hành vi thực sự là kì quặc một chút so với ví dụ của bạn chỉ ra, trong đó bạn chỉ nhận được FALSE khi bạn có một yếu tố ở phía bên trái của %in%:

> a %in% b 
[1] FALSE 
> c(a, a) %in% b 
[1] TRUE TRUE 

Như ngụ ý của ý kiến, %in% chỉ cần gọi match, vì vậy vấn đề có thể được nhìn thấy có quá:

> match(a, b) 
[1] NA 
> match(c(a, a), b) 
[1] 1 1 

những lập luận quan trọng đối với %in%matchxtable, trong đó một trong hai chức năng tìm kiếm x trong table. Dưới mui xe, R thực hiện điều này trong hàm match5 được xác định trong unique.c. Trong trường hợp bạn có nhiều hơn một x, match5 sẽ tạo bảng băm từ table để bật tra cứu nhanh. Nếu bạn khai thác mã, bạn sẽ thấy rằng việc so sánh được thực hiện trong một hàm có tên là sequal, trả về Seql(STRING_ELT(x, i), STRING_ELT(y, j)) (tốt, nó thực sự phức tạp hơn một chút so với điều này *). Sau đó, nếu bạn đi nhìn vào Seql trong memory.c, bạn sẽ tìm thấy:

int result = !strcmp(translateCharUTF8(a), translateCharUTF8(b)); 

nào, như bạn có thể thấy, chuyển đổi chuỗi sang UTF-8.

Tuy nhiên, nếu x chỉ có một yếu tố, đó là ngớ ngẩn phải đi qua những rắc rối của việc tạo ra một bảng băm, vì chúng ta chỉ có thể quét qua table một lần để xem nếu x là ở đó. Trong 3.3.0, mã để kiểm tra sự bình đẳng giữa x và mỗi phần tử của table không sử dụng Seql và không chuyển đổi chuỗi thành UTF-8. Nhưng bắt đầu từ 3.3.1, Seql được sử dụng, do đó hành vi được khắc phục.

* Một chút sang một bên trên chuỗi bình đẳng: R sẽ thực sự lưu trữ các chuỗi để nó không phải lưu trữ một loạt các bản sao. Vì vậy, nếu hai chuỗi ở cùng một vị trí, chúng bằng nhau và không cần kiểm tra thêm nữa!

> .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ác vấn đề liên quan