Skip to content
This repository has been archived by the owner on Jul 6, 2021. It is now read-only.
/ hash_op Public archive

A Ruby library of functions to access and manipulate hash data structures.

Notifications You must be signed in to change notification settings

rchampourlier/hash_op

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HashOp

A Ruby library of functions to access and manipulate hash data structures.

Build Status Code Climate Coverage Status

Installation

Add this line to your application's Gemfile:

gem 'hash_op'

And then execute:

$ bundle

Or install it yourself as:

$ gem install hash_op

Usage

Available operations

Deep Access

HashOp::Deep.fetch({a: {b: {c: 1}}}, :'a.b.c')
=> 1

HashOp::Deep.merge({ a: { b: { c: 1 } } }, :'a.b.c', 2)
=> {
  :a => {
    :b => {
      :c => 2
    }
  }
}

Filter

hashes = [
  { value: 123, regexp: "itsamatch", proc: "1+1" },
  { value: 123, regexp: "abcdef", proc: "1+2" },
  { value: 234, regexp: "abcdef", proc: "1+2" }
]
criteria = {
  path: :value,
  matching_object: 123
}
HashOp::Filter.filter(hashes, { value: 123 })
=> [
  [0] {
      :proc => "1+1",
    :regexp => "itsamatch",
     :value => 123
  },
  [1] {
      :proc => "1+2",
    :regexp => "abcdef",
     :value => 123
  }
]
HashOp::Filter.filter(hashes, { value: 123, regexp: /match/ })
=> [
  [0] {
      :proc => "1+1",
    :regexp => "itsamatch",
     :value => 123
  }
]
HashOp::Filter.filter(hashes, { proc: ->(x) { eval(x) == 2 } })
=> [
  [0] {
      :proc => "1+1",
    :regexp => "itsamatch",
     :value => 123
  }
]

Internally, `HashOp::Filter::filter` uses
`HashOp::Filter::match?(hash, criteria)` which you can
use too.

Mapping

hash = {a: { b: { c: 1 } } }
mapping = { r: { path: :'a.b.c' } }
HashOp::Mapping.apply_mapping(hash, mapping)
=> {
  :r => 1
}

hash = {
  raw: { deep: 'raw_value' },
  time: '2015-07-06 03:37:13 +0200',
  mapped_hash: {
    raw: { deep: 'deep_raw_value' },
    time: '2014-07-06 03:37:13 +0200'
  },
  parseable_string: 'a=1;b=2;t=2013-07-06 03:37:13 +0200',
  array: [
    '2015-07-06 03:37:13 +0200',
    '2014-07-06 03:37:13 +0200',
    '2013-07-06 03:37:13 +0200'
  ]
}
mapping = {
  raw: { path: :'raw.deep' },
  time: { path: :time, type: :time },
  raw_from_mapped_hash: {
    path: :'mapped_hash.raw.deep',
  },
  time_from_mapped_hash: {
    path: :'mapped_hash.time',
    type: :time
  },
  values_from_parseable_string: {
    path: :parseable_string,
    type: :parseable_string,
    parsing_mapping: {
      value: { regexp: 'a=(\d)+;' },
      time: {
        regexp: 't=(.*)$',
        type: :time
      }
    }
  },
  times_from_array: {
    type: :array,
    path: :array,
    item_mapping: { type: :time }
  }
}
HashOp::Mapping.apply_mapping(hash, mapping)
=> {
                           :raw => "raw_value",
          :raw_from_mapped_hash => "deep_raw_value",
                          :time => 2015-07-06 03:37:13 +0200,
         :time_from_mapped_hash => 2014-07-06 03:37:13 +0200,
              :times_from_array => [
    [0] 2015-07-06 03:37:13 +0200,
    [1] 2014-07-06 03:37:13 +0200,
    [2] 2013-07-06 03:37:13 +0200
  ],
  :values_from_parseable_string => {
     :time => 2013-07-06 03:37:13 +0200,
    :value => "1"
  }
}

Grouping

hashes = [
  {
    grouping_path: 'A',
    value: 1,
    node: { 'deep_grouping_path': 'AA' }
  },
  {
    grouping_path: 'B',
    value: 2,
    node: { 'deep_grouping_path': 'BB' }
  },
  {
    grouping_path: 'A',
    value: 3,
    node: { 'deep_grouping_path': 'AB' }
  },
  {
    grouping_path: 'A',
    value: 4,
    node: { 'deep_grouping_path': 'AA' }
  }
]
HashOp::Grouping.group_on_path(hashes, :grouping_path)
=> {
  "A" => [
    [0] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AA"
      },
              :value => 1
    },
    [1] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AB"
      },
              :value => 3
    },
    [2] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AA"
      },
              :value => 4
    }
  ],
  "B" => [
    [0] {
      :grouping_path => "B",
               :node => {
        :deep_grouping_path => "BB"
      },
              :value => 2
    }
  ]
}
HashOp::Grouping.group_on_path(hashes, :'node.deep_grouping_path')
=> {
  "AA" => [
    [0] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AA"
      },
              :value => 1
    },
    [1] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AA"
      },
              :value => 4
    }
  ],
  "AB" => [
    [0] {
      :grouping_path => "A",
               :node => {
        :deep_grouping_path => "AB"
      },
              :value => 3
    }
  ],
  "BB" => [
    [0] {
      :grouping_path => "B",
               :node => {
        :deep_grouping_path => "BB"
      },
              :value => 2
    }
  ]
}
HashOp::Grouping.group_on_paths(hashes, [:grouping_path, :'node.deep_grouping_path'])
=> {
  "A" => {
    "AA" => [
      [0] {
        :grouping_path => "A",
                 :node => {
          :deep_grouping_path => "AA"
        },
                :value => 1
      },
      [1] {
        :grouping_path => "A",
                 :node => {
          :deep_grouping_path => "AA"
        },
                :value => 4
      }
    ],
    "AB" => [
      [0] {
        :grouping_path => "A",
                 :node => {
          :deep_grouping_path => "AB"
        },
                :value => 3
      }
    ]
  },
  "B" => {
    "BB" => [
      [0] {
        :grouping_path => "B",
                 :node => {
          :deep_grouping_path => "BB"
        },
                :value => 2
      }
    ]
  }
}

See specs for more details on each operation and operations not documented here.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/rchampourlier/hash_op. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

Revisions

0.3.0

  • Added Read.values_at_path
  • Minor fixes

0.2.0

  • Removed some operations that made no real sense (Math.sum and Math.sum_two).
  • Renamed DeepAccess to Deep.
  • Renamed Merge.merge to Merge.flat and Merge.merge_by_group to Merge.by_group.

0.1.0

Initial version

About

A Ruby library of functions to access and manipulate hash data structures.

Topics

Resources

Code of conduct

Stars

Watchers

Forks

Packages

No packages published