GithubHelp home page GithubHelp logo

dictr's Introduction

dict provides a new data structure specialized for representing dictionaries with string keys.

Install the package using devtools:

devtools::install_github('stefano-meschiari/dict')

and import the library with library:

library(dict)

A proper dictionary class

The new class dict can be used to represent a heterogeneous dictionary with character keys. dicts have a few advantages over named lists:

  • Every value is uniquely associated with a key (no holes).
  • Keys are unique and cannot be repeated.
  • Printing of dicts is more compact.
  • Keys are never partially matched (a key named test will not match with t or te).
  • A dict can have default values for non-existing keys.
  • Dicts can contain NULL values.

This library also provides some useful functions for manipulating dictionary-like objects.

Creating a dictionary

The dict function can be used to create a new dictionary:

d <- dict(color='blue', pattern='solid', width=3)

You can create a dictionary out of a list of keys and values using make_dict:

d <- make_dict(keys=c('color', 'pattern', 'width'),
               values=c('blue', 'solid', 3))

You can convert a named list or vector to a dictionary using as_dict:

d <- as_dict(list(color='blue', pattern='solid', width=3))
d <- as_dict(c("a" = 1, "b" = 2))

Printing looks nice:

print(d)
##   $ color : [1] "blue"
## $ pattern : [1] "solid"
##   $ width : [1] 3

You can use a shorthand and leave keys implicit (this is similar to the ES6 object literal shorthand). dict will try to create implicit keys based on the arguments:

operating_system <- 'Amiga OS'
version <- '3.1'
cpu <- '68040'

machine <- dict(operating_system, version, cpu)

print(machine)
## $ operating_system : [1] "Amiga OS"
##          $ version : [1] "3.1"
##              $ cpu : [1] "68040"

Accessing entries

You can access values using the familiar R syntax for lists:

d <- dict(color='blue', pattern='solid', width=3)

d$color                   # blue
d[['pattern']]            # solid
d['color', 'pattern']  # a sub-dictionary with keys color and pattern

You can get keys and values using the keys and values functions:

keys(d)      # c('color', 'pattern', 'width')
values(d)    # list('blue', 'solid', 3)

You can get a list of "entries" (each element being a list with key and value). This is useful for iteration:

for (entry in entries(d)) {
  cat(entry$key, ' = ', entry$value)
}

You can use the map_dict function to map over keys and values, and the keep_dict and discard_dict to filter entries. These functions are specializations of the map, keep and discard family of functions in purrr to the dictionary class.

# Returns a dict with the same keys and squared values
d <- dict(a=1, b=2, c=3)
map_dict(d, function(k, v) v^2)

Setting entries

Entries can be set just like regular lists:

d <- dict(first='Harrison', last='Solo')  # first=Harrison, last=Solo
d$last <- 'Ford'                          # first=Harrison, last=Ford
d[['first']] <- 'Leia'                    # first=Leia, last=Ford
d[c('last', 'title')] <- c('Organa', 'Princess') # first=Leia, last=Organa, title=Princess

Setting an entry to NULL does not delete the entry, but instead sets the entry to NULL. To delete one or more entries, use the omit function:

d <- dict(a=1, c=3)
d$b <- NULL         # a=1, b=NULL, c=3
d <- omit(a, 'a')   # b=NULL, c=3

Utility functions

A few utility functions inspired by the Underscore library:

  • invert(dict) returns a dictionary where keys and values are swapped.
  • has(dict, key) returns TRUE if dict contains key.
  • omit(dict, key1, key2, ...) returns a new dictionary omitting all the specified keys.
  • extend(dict, dict1, ...) copies all entries in dict1 into dict, overriding any existing entries and returns a new dictionary.
  • defaults(dict, defaults) fill in entries from defaults into dict for any keys missing in dict.

The following functions specialize functions from the purrr library to dictionary objects:

  • map_dict(dict, fun, ...) calls a function on each (key, value) pair and builds a dictionary from the transformed input.
  • keep_dict(dict, fun) and discard_dict(dict, fun) keep or discard entries based on the function or predicate.
  • compact_dict(dict) removes any entries with NULL values.

Default dictionaries

You can create a dictionary with default values using default_dict. Any time a non-existing key is accessed, the default value is returned.

salaries <- default_dict(employee_a = 50000,
                         employee_b = 100000,
                         default = 65000)

You can provide a default value for an existing dictionary by setting its default attribute:

attr(salaries, 'default') <- 70000

Strict dictionaries

You can create a strict dictionary using strict_dict. Any time a non-existing key is accessed, an exception is thrown using stop().

# Associating each letter with a number
letters_to_numbers <- strict_dict(a=1, b=2, c=3, d=4) # etc.

# Accessing an existing key, that's OK!
print(letters_to_numbers$a)
## [1] 1
# Accessing a non-letter will throw!
tryCatch(letters_to_numbers$notaletter, error=function(e) print(e))
## <simpleError in `$.dict`(letters_to_numbers, notaletter): Attempted access of non-existing keynotaletter>

Immutable collections

You can turn any collection (lists, vectors, and dicts) into an immutable collection using the immutable function. Such a collection cannot be modified using the [, [[ and $ operators; otherwise, it will behave the same as the original collection. The immutable_dict function creates an immutable dictionary.

const_letters <- immutable(letters)

# Will throw an error
const_letters[1] <- '1' 
## Error in `[<-.immutable`(`*tmp*`, 1, value = "1"): Attempting to mutate an immutable collection.
physical_constants <- immutable_dict(
  astronomical_unit = 1.5e11,
  speed_of_light = 3e8,
  gravitational_constant = 6.7e-11
)

# Will throw an error
physical_constants$speed_of_light = 1
## Error in `$<-.immutable`(`*tmp*`, "speed_of_light", value = 1): Attempting to mutate an immutable collection.

dictr's People

Contributors

stefano-meschiari avatar deleetdk avatar

Stargazers

Polis Law avatar David Liao avatar  avatar Russell Smith avatar Paolo avatar Pierre Formont avatar Yixuan Qiu avatar timelyportfolio avatar  avatar Kieran Mace avatar Brodie Gaslam avatar Jonathan Carroll avatar tdn avatar Arvi Sreenivasan avatar m-dz avatar Akshay Paropkari avatar  avatar  avatar James Guillochon avatar LM avatar

Watchers

timelyportfolio avatar James Cloos avatar  avatar tdn avatar

dictr's Issues

Errors in the readme

Interesting package. :)

There are errors in the README:

devtools::install_github('stefano-meschiari/nicr')

Should be nicer.

mapkv(d, function(k, v) paste(key, as.character(v)))

key should be k.

d2 <- dict(a=1, b=2, c=3)
mapkv_dict(d, function(k, v) v^2)

Should be d2. Otherwise it uses the other dict which has non-numeric values.

defaults(dict, defaults) fill in entries from defaults into dict for any keys missing in dict.

This should be default, I think. defaults is a plyr function. E.g.:

> d
  $ color : [1] "blue"
$ pattern : [1] "solid"
  $ width : [1] 3
> default(d) = "test"
> d$nonexistent_entry
[1] "test"

So, the function works.

struct: constraints and types

One can cause havoc by having a struct that has constraints and giving them arguments that have a wrong type. For instance:

> PositiveVector <- struct('PositiveVector',
+                          x = 1 ~ { x > 0 },
+                          y = 1 ~ { y > 0 },
+                          z = 1 ~ { z > 0 })
> PositiveVector(x = "sd")
Struct of class  PositiveVector 
$ x : [1] "sd"
$ y : [1] 1
$ z : [1] 1

Here we supposedly have a vector of positive values, except that one of the values is a chr. It's because chr apparently always satisfies > 0:

> "a" > 0
[1] TRUE
> "a" < 0
[1] FALSE
> "a" == 0
[1] FALSE
> "test" > 0
[1] TRUE

Not sure what the semantics for comparing chr to num is in R. You probably want to force a type check for these too.

`entries` print method issues

It fails, and then it also leaves stdout in a broken state.

> library(dict)
>  d <- dict(color="blue", pattern='solid', width=3)
> entries(d)
  $ color : Error in print.default(value, digits = digits) : 
  promise already under evaluation: recursive default argument reference or earlier problems?
> "hello"
Error: invalid connection
> sink()
Error in sink() : invalid connection
> sink(NULL)
Warning message:
In sink(NULL) : no sink to remove
> "hello"
[1] "hello"

version:

> packageDescription("dict")
Package: dict
Type: Package
Title: A dictionary class for R
Version: 0.5
Date: 2016-08-07
Authors@R: person("Stefano", "Meschiari",
        email="[email protected]", role=c("aut", "cre"))
Description: Provides an implementation of a dictionary class with
        character keys. It offers several features over named lists,
        including unique keys, no partial matching, compact printing,
        default values, and ability to store NULLs.
License: MIT
LazyData: TRUE
Imports: purrr, stringr
RoxygenNote: 5.0.1
Suggests: knitr, rmarkdown, testthat
VignetteBuilder: knitr
Author: Stefano Meschiari [aut, cre]
Maintainer: Stefano Meschiari <[email protected]>
Built: R 3.3.1; ; 2016-09-08 12:53:27 UTC; unix
RemoteType: github
RemoteHost: https://api.github.com
RemoteRepo: dict
RemoteUsername: stefano-meschiari
RemoteRef: master
RemoteSha: 3a6d5b920eabb0db65b7b2729aca430d4b49b347
GithubRepo: dict
GithubUsername: stefano-meschiari
GithubRef: master
GithubSHA1: 3a6d5b920eabb0db65b7b2729aca430d4b49b347

-- File: /Library/Frameworks/R.framework/Versions/3.3/Resources/library/dict/Meta/package.rds

and system:

> sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: OS X 10.9.5 (Mavericks)

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] dict_0.5

loaded via a namespace (and not attached):
 [1] magrittr_1.5    tools_3.3.1     withr_1.0.2     Rcpp_0.12.7    
 [5] memoise_1.0.0   stringi_1.1.1   stringr_1.1.0   digest_0.6.10  
 [9] devtools_1.12.0 purrr_0.2.2    

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.