比较数字和整数值有时为TRUE,有时为FALSE。

huangapple go评论67阅读模式
英文:

Comparing numeric and integer values sometimes gives TRUE and sometimes FALSE

问题

我使用 %in% 比较两个列表,一个包含 数值 向量,另一个包含 对应的整数 值。结果非常奇怪;有时是 TRUE,有时是 FALSE,我无法弄清楚为什么。

例如,下面的代码会返回 TRUE

list(c(1, 1)) %in% list(c(1L, 1L))

然而,如果我们将向量中的第二个数字更改为2和2L,就会返回 FALSE

list(c(1, 2)) %in% list(c(1L, 2L))

将第二个数字更改为3或4又会返回 TRUE

list(c(1, 3)) %in% list(c(1L, 3L))
list(c(1, 4)) %in% list(c(1L, 4L))

再次使用其他值会产生 FALSE,但我无法看出任何模式。例如,使用8和9会返回 FALSE

list(c(8, 9)) %in% list(c(8L, 9L))

有人知道为什么会这样吗?这真的令人困惑,我完全不明白为什么会发生这种情况。

英文:

I use %in% to compare two lists, one with a vector of numeric values and the other with corresponding integer values. The result is really weird; sometimes TRUE and sometimes FALSE and I can't figure out why.

For example the code below gives TRUE

list(c(1, 1)) %in% list(c(1L, 1L))

However, if we change the second number in the vectors to 2 and 2L we get FALSE

list(c(1, 2)) %in% list(c(1L, 2L))

Changing the second number to 3 or 4 gives TRUE again.

list(c(1, 3)) %in% list(c(1L, 3L))
list(c(1, 4)) %in% list(c(1L, 4L))

Using some other values again produces FALSE but I can't see any pattern to this. For example using 8 and 9 results in FALSE:

list(c(8, 9)) %in% list(c(8L, 9L))

Does anyone know why this is the case? It's really baffling and I'm completely lost why it's happening.

答案1

得分: 7

%in% 是使用 match() 实现的(打印 `%in%` 会显示 match(x, table, nomatch = 0L) > 0L),而 ?match 表示:

因子、原始向量和列表在比较之前会被转换为字符向量

现在让我们比较一下:

  • as.character(list(c(1,1))) 是 "c(1,1)"(整数等效值也一样)
  • as.character(list(c(1,2))) 是 "c(1,2)"
  • 但是... as.character(list(c(1L, 2L))) 是 "1:2",因为 R 认为连续的整数序列可以被压缩成另一种表示方式(ALTREP)

(另一个例子,as.character(list(7L, 8L, 9L)) 是 "7:9",而不是 "c(7, 8, 9)")

作为一种解决方法,您可以显式地使用 as.numeric() 转换向量...

您还可以(如@user2554330建议的)向您的列表添加一个类属性(class(L) <- c("mylist", "list")),并定义一个 mtfrm.mylist 方法,以稍微更有原则的方式执行强制转换为数字然后再转换为字符的操作...

英文:

This is a bit tricky. %in% is implemented using match() (printing `%in%` shows match(x, table, nomatch = 0L) > 0L), and ?match says

> Factors, raw vectors and lists are converted to character vectors

before comparison. Now let's compare:

  • as.character(list(c(1,1))) is "c(1,1)" (and the same for the integer equivalent)
  • as.character(list(c(1,2))) is "c(1,2)"
  • but ... as.character(list(c(1L, 2L))) is "1:2" (!), because R recognizes a contiguous integer sequence as one that can be collapsed to an alternative/compact representation (ALTREP)

(As another example, as.character(list(7L, 8L, 9L)) is "7:9", not "c(7, 8, 9)")

As a workaround, you could explicitly convert the vectors with as.numeric() ...

You could also (as suggested by @user2554330) add a class attribute to your lists (class(L) <- c("mylist", "list")) and define a mtfrm.mylist method to do the coercion-to-numeric-before-character stuff in a slightly more principled way ...

huangapple
  • 本文由 发表于 2023年2月18日 00:09:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75486678.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定