multihash 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/lib/multihash/multihash.rb +83 -5
  2. metadata +9 -7
  3. checksums.yaml +0 -7
@@ -3,6 +3,30 @@
3
3
  # several mappings to a single value, without doing anything particularly
4
4
  # gross with Array#include? lookups.
5
5
  class MultiHash
6
+ attr_accessor :immutable
7
+ alias_method :immutable?, :immutable
8
+
9
+ HASH_METHOD_WHITELIST = [
10
+ :[],
11
+ :assoc,
12
+ :default,
13
+ :empty?,
14
+ :each,
15
+ :each_key,
16
+ :each_pair,
17
+ :each_value,
18
+ :fetch,
19
+ :keys,
20
+ :select,
21
+ :values_at
22
+ ]
23
+
24
+ HASH_METHOD_WHITELIST.each do |mth|
25
+ define_method mth do |*args, &blk|
26
+ @_hash.send(mth, *args, &blk)
27
+ end
28
+ end
29
+
6
30
  # Initialize an immutable multihash with the provided hash as its source.
7
31
  # For example, we might want to look up the nation which produces different
8
32
  # types of cars:
@@ -15,16 +39,70 @@ class MultiHash
15
39
  #
16
40
  # @param original_hash [Hash<Array|Object, Object>] the hash to convert into
17
41
  # a multihash, with arrays or single objects as keys.
18
- def initialize(original_hash)
19
- @_hash = Hash.new
42
+ def initialize(original_hash={}, immutable=true)
43
+ @_hash = Hash.new(original_hash.default)
44
+ @immutable = immutable
45
+
46
+ groups = []
20
47
 
21
48
  original_hash.each do |orig_key, value|
22
49
  key_array = orig_key.is_a?(Array) && orig_key || [orig_key]
23
- key_array.each { |k| @_hash[k] = value }
50
+ groups << key_array
51
+ key_array.each { |k| map_value(k, value) }
24
52
  end
53
+
54
+ store_groups(groups) unless immutable?
55
+ end
56
+
57
+ def grouped
58
+ Hash[@_groups.values.map { |g| [g, self[g.first]] }]
59
+ end
60
+
61
+ def set(key, value)
62
+ fail 'Cannot modify an immutable MultiHash!' if immutable?
63
+ split_key_from_group(key)
64
+ map_value(key, value)
65
+ end
66
+ alias_method :[]=, :set
67
+
68
+ def set_group(key, value)
69
+ fail 'Cannot modify an immutable MultiHash!' if immutable?
70
+ @_groups[key].each { |k| map_value(k, value) }
71
+ end
72
+
73
+ def to_h
74
+ @_hash
75
+ end
76
+
77
+ def values
78
+ @_values ||= @_hash.values.uniq
79
+ end
80
+
81
+ def self.[](args)
82
+ MultiHash.new(Hash[args])
83
+ end
84
+
85
+ private
86
+
87
+ def dirty
88
+ @_grouped = nil
89
+ @_values = nil
90
+ end
91
+
92
+ def map_value(key, value)
93
+ dirty
94
+ @_hash[key] = value
95
+ end
96
+
97
+ def split_key_from_group(key)
98
+ former_group = @_groups[key]
99
+ other_groups = @_groups.values - former_group
100
+ new_group = key.is_a?(Array) ? key : [key]
101
+ modified_group = former_group - new_group
102
+ store_groups(other_groups + modified_group + new_group)
25
103
  end
26
104
 
27
- def [](key)
28
- @_hash[key]
105
+ def store_groups(groups)
106
+ @_groups = MultiHash.new(Hash[groups.map { |g| [g, g] }])
29
107
  end
30
108
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multihash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Blake Hyde
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-12-17 00:00:00.000000000 Z
12
+ date: 2014-12-18 00:00:00.000000000 Z
12
13
  dependencies: []
13
14
  description: MultiHash allows multiple keys to the same value, concisely.
14
15
  email: syrion@gmail.com
@@ -20,25 +21,26 @@ files:
20
21
  homepage: https://github.com/asthasr/multihash
21
22
  licenses:
22
23
  - MIT
23
- metadata: {}
24
24
  post_install_message:
25
25
  rdoc_options: []
26
26
  require_paths:
27
27
  - lib
28
28
  required_ruby_version: !ruby/object:Gem::Requirement
29
+ none: false
29
30
  requirements:
30
- - - ">="
31
+ - - ! '>='
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0'
33
34
  required_rubygems_version: !ruby/object:Gem::Requirement
35
+ none: false
34
36
  requirements:
35
- - - ">="
37
+ - - ! '>='
36
38
  - !ruby/object:Gem::Version
37
39
  version: '0'
38
40
  requirements: []
39
41
  rubyforge_project:
40
- rubygems_version: 2.2.2
42
+ rubygems_version: 1.8.23
41
43
  signing_key:
42
- specification_version: 4
44
+ specification_version: 3
43
45
  summary: A many-to-one, immutable hash.
44
46
  test_files: []
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: dbead59572ba7080786ff23f566971f2c5323d0d
4
- data.tar.gz: 21d075eb849f528c9849ec17ecba9d87ca51a5e3
5
- SHA512:
6
- metadata.gz: 8d2aa119dabc2d5980152b50a1a7b53bfb205b51c98db9c9e67b4ebbb035969bf327b5983d053b6b5257b00f840818e0a22d301175590aeeb5d7535d75db2a92
7
- data.tar.gz: abb7eff1d113406685f45e47fade2b826a6a2118cd244e94796c04b4479d59990ffcee0ecca4e44742f61715037dc1d617aa56908f0e86ad0e0763a1c98ad99e