0

I need to map an integer to an integer in R. In python this is the job of a dictionary

>>> a = { 4: 1, 5: 2, 6:3 }
>>> a[5]
2

but no such thing exists in R. A vector does not work:

 a<- c(1,2,3)
> a
[1] 1 2 3
> names(a) <- c(5,6,7)
> a
5 6 7 
1 2 3 
> a[[5]]
Error in a[[5]] : subscript out of bounds

a list doesn't work either

> a<- list(1,2,3)
> a
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

> names(a) <- c(4, 5, 6)
> a
$`4`
[1] 1

$`5`
[1] 2

$`6`
[1] 3

> a[[6]]
Error in a[[6]] : subscript out of bounds
Stefano Borini
  • 138,652
  • 96
  • 297
  • 431
  • You just called it wrong. Try `a['5']` or `a[['5']]`. This should work in both lists and named vectors – Sotos Feb 06 '20 at 13:44
  • @sotos That would require that I access it as a string. – Stefano Borini Feb 06 '20 at 13:45
  • Oh, you need to call it as integer? Then you can't because R will take the integer as the index, not as the name – Sotos Feb 06 '20 at 13:47
  • @sotos I added a python example. Is there any data structure I can use for this purpose? i'd prefer not to pass through string if possible. – Stefano Borini Feb 06 '20 at 13:48
  • No but you should be able to hack it. Maybe build a vector of the form `x <- c(NA, NA, NA, 1, 2, 3)`, in which case `x[5]` will give you `2` – Sotos Feb 06 '20 at 13:51
  • @Sotos I can't. I am mapping id numbers to values, and the id numbers can be huge. Unless the vector code does run length encoding I would waste a massive amount of memory – Stefano Borini Feb 06 '20 at 13:53
  • Then definitely not. Answer below with `hashmap` should suit you – Sotos Feb 06 '20 at 13:55

4 Answers4

5

There are some dictionaries in R.

I would suggest the hashmap package for your case.

library(hashmap)
H <- hashmap(c(2, 4, 6), c(99, 999, 9999))
H
##   (numeric) => (numeric)     
## [+2.000000] => [+99.000000]  
## [+4.000000] => [+999.000000] 
## [+6.000000] => [+9999.000000]
H[[4]]
# [1] 999

If you want "true" integers:

H <- hashmap(c(2L, 4L, 6L), c(99L, 999L, 9999L))
H
## (integer) => (integer)
##       [2] => [99]     
##       [4] => [999]    
##       [6] => [9999] 
Stéphane Laurent
  • 75,186
  • 15
  • 119
  • 225
2

For good performance you use match.

k<-c(5,6,7)
v<-c(1,2,3)

x<-c(5,5,6)

v[match(x,k)] 

In fact, if your v is just 1:n it is enough to do

match(x, k)

as match returns the index in the array you are doing lookup in.

Der Gnirreh
  • 198
  • 11
1

In your last example this should work (string not numeric):

a <- list(1,2,3)
names(a) <- c(4, 5, 6)    

a[["6"]]
a[[as.character(6)]]
Marta
  • 3,032
  • 3
  • 17
  • 34
1

A less than optimal possible solution would be to assign the integers into position of their integers in a vector:

a[c(5:7)]<-1:3
a[6]
> [1] 2

A drawback (or benefit, depends on your needs) is that a[1] would yield an NA

iod
  • 7,412
  • 2
  • 17
  • 36