map 5.5.0 → 5.6.1
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.
- data/a.rb +16 -5
- data/lib/map.rb +54 -67
- data/map.gemspec +1 -1
- data/test/map_test.rb +6 -17
- metadata +2 -2
data/a.rb
CHANGED
@@ -1,9 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
1
3
|
# -*- encoding : utf-8 -*-
|
2
|
-
require './lib/map.rb'
|
3
4
|
|
4
|
-
|
5
|
+
def assert(&block)
|
6
|
+
block.call
|
7
|
+
end
|
8
|
+
|
9
|
+
m = Map.new
|
10
|
+
m.set(:a, :b, :c, 42)
|
11
|
+
p m.get(:a, :b, 0)
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
m = Map.new
|
16
|
+
m.set(:a, 0, 42)
|
17
|
+
p m.get(:a, :b, 0)
|
18
|
+
|
5
19
|
|
6
|
-
opts = Map.options_for!(args)
|
7
20
|
|
8
|
-
p args
|
9
|
-
p opts
|
data/lib/map.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
class Map < Hash
|
3
|
-
Version = '5.
|
3
|
+
Version = '5.6.1' unless defined?(Version)
|
4
4
|
Load = Kernel.method(:load) unless defined?(Load)
|
5
5
|
|
6
6
|
class << Map
|
@@ -721,8 +721,7 @@ class Map < Hash
|
|
721
721
|
when Hash
|
722
722
|
collection.has_key?(key)
|
723
723
|
when Array
|
724
|
-
|
725
|
-
(0...collection.size).include?(Integer(key))
|
724
|
+
(0...collection.size).include?((Integer(key) rescue -1))
|
726
725
|
end
|
727
726
|
end
|
728
727
|
|
@@ -736,45 +735,70 @@ class Map < Hash
|
|
736
735
|
spec[keys] = value
|
737
736
|
end
|
738
737
|
|
739
|
-
|
740
|
-
|
738
|
+
begin
|
739
|
+
spec.each do |keys, value|
|
740
|
+
keys = Array(keys).flatten
|
741
|
+
collection = self
|
742
|
+
key = keys.pop
|
741
743
|
|
742
|
-
|
743
|
-
|
744
|
-
|
744
|
+
while((k = keys.shift)) do
|
745
|
+
k = alphanumeric_key_for(k)
|
746
|
+
collection = collection[k]
|
747
|
+
end
|
745
748
|
|
746
|
-
if keys.size <= 1
|
747
|
-
key = keys.first
|
748
749
|
collection[key] = value
|
749
|
-
next
|
750
750
|
end
|
751
|
+
rescue
|
752
|
+
spec.each do |keys, value|
|
753
|
+
keys = Array(keys).flatten
|
754
|
+
|
755
|
+
collection = self
|
756
|
+
|
757
|
+
if keys.size <= 1
|
758
|
+
key = keys.first
|
759
|
+
collection[key] = value
|
760
|
+
next
|
761
|
+
end
|
762
|
+
|
763
|
+
leaf_for(keys, :autovivify => true) do |leaf, key|
|
764
|
+
leaf[key] = value
|
765
|
+
end
|
766
|
+
end
|
767
|
+
end
|
751
768
|
|
752
|
-
|
769
|
+
return spec.values
|
770
|
+
end
|
771
|
+
|
772
|
+
def leaf_for(keys, options = {}, &block)
|
773
|
+
collection = self
|
774
|
+
key = nil
|
753
775
|
|
754
|
-
|
755
|
-
|
776
|
+
keys.each_cons(2) do |a, b|
|
777
|
+
a, b = alphanumeric_key_for(a), alphanumeric_key_for(b)
|
756
778
|
|
757
|
-
|
779
|
+
exists = collection_has_key?(collection, a)
|
758
780
|
|
759
|
-
|
760
|
-
|
761
|
-
|
781
|
+
case b
|
782
|
+
when Numeric
|
783
|
+
if options[:autovivify]
|
762
784
|
collection[a] = [] unless exists
|
763
|
-
|
785
|
+
end
|
786
|
+
raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }][#{ b.inspect }]") unless collection[a].is_a?(Array)
|
764
787
|
|
765
|
-
|
766
|
-
|
767
|
-
collection[a] =
|
768
|
-
|
769
|
-
|
770
|
-
collection = collection[a]
|
771
|
-
key = b
|
788
|
+
when String, Symbol
|
789
|
+
if options[:autovivify]
|
790
|
+
collection[a] = Map.new unless exists
|
791
|
+
end
|
792
|
+
raise(IndexError, "(#{ collection.inspect })[#{ a.inspect }][#{ b.inspect }]") unless collection[a].is_a?(Map)
|
772
793
|
end
|
773
794
|
|
774
|
-
collection
|
795
|
+
collection = collection[a]
|
796
|
+
key = b
|
775
797
|
end
|
776
798
|
|
777
|
-
|
799
|
+
leaf = collection
|
800
|
+
|
801
|
+
block ? block.call(leaf, key) : [leaf, key]
|
778
802
|
end
|
779
803
|
|
780
804
|
def rm(*args)
|
@@ -841,49 +865,12 @@ class Map < Hash
|
|
841
865
|
Map.alphanumeric_key_for(key)
|
842
866
|
end
|
843
867
|
|
844
|
-
## key path support
|
845
|
-
#
|
846
|
-
def self.dot_key_for(*keys)
|
847
|
-
dot = keys.compact.flatten.join('.')
|
848
|
-
dot.split(%r/\s*[,.]\s*/).map{|part| part =~ %r/^\d+$/ ? Integer(part) : part}
|
849
|
-
end
|
850
|
-
|
851
|
-
def self.dot_keys
|
852
|
-
@@dot_keys = {} unless defined?(@@dot_keys)
|
853
|
-
@@dot_keys
|
854
|
-
end
|
855
|
-
|
856
|
-
def self.dot_keys?
|
857
|
-
ancestors.each do |ancestor|
|
858
|
-
return dot_keys[ancestor] if dot_keys.has_key?(ancestor)
|
859
|
-
end
|
860
|
-
false
|
861
|
-
end
|
862
|
-
|
863
|
-
def dot_keys?
|
864
|
-
@dot_keys = false unless defined?(@dot_keys)
|
865
|
-
@dot_keys
|
866
|
-
end
|
867
|
-
|
868
|
-
def self.dot_keys!(boolean = true)
|
869
|
-
dot_keys[self] = !!boolean
|
870
|
-
end
|
871
|
-
|
872
|
-
def dot_keys!(boolean = true)
|
873
|
-
@dot_keys = !!boolean
|
874
|
-
end
|
875
|
-
|
876
868
|
def self.key_for(*keys)
|
877
|
-
return keys.flatten
|
878
|
-
self.dot_key_for(*keys)
|
869
|
+
return keys.flatten
|
879
870
|
end
|
880
871
|
|
881
872
|
def key_for(*keys)
|
882
|
-
|
883
|
-
self.class.dot_key_for(*keys)
|
884
|
-
else
|
885
|
-
self.class.key_for(*keys)
|
886
|
-
end
|
873
|
+
self.class.key_for(*keys)
|
887
874
|
end
|
888
875
|
|
889
876
|
## TODO - technically this returns only leaves so the name isn't *quite* right. re-factor for 3.0
|
data/map.gemspec
CHANGED
data/test/map_test.rb
CHANGED
@@ -349,26 +349,10 @@ Testing Map do
|
|
349
349
|
assert{ m[:A].is_a?(Array) }
|
350
350
|
assert{ m[:A].size == 3}
|
351
351
|
assert{ m[:A][2] == 'forty-two' }
|
352
|
-
assert{ m[:x][:y].is_a?(
|
352
|
+
assert{ m[:x][:y].is_a?(Map) }
|
353
353
|
assert{ m[:x][:y][:z] == 42.0 }
|
354
354
|
end
|
355
355
|
|
356
|
-
testing 'that maps can support compound key/val setting via key.dot notation' do
|
357
|
-
m = Class.new(Map){ dot_keys! }.new
|
358
|
-
assert{ m.set('a.b.c', 42) }
|
359
|
-
assert{ m[:a][:b][:c] == 42 }
|
360
|
-
assert{ m.get('a.b.c') == 42 }
|
361
|
-
assert{ m.set('x.y.z' => 42.0, 'A.2' => 'forty-two') }
|
362
|
-
assert{ m[:A].is_a?(Array) }
|
363
|
-
assert{ m[:A].size == 3}
|
364
|
-
assert{ m[:A][2] == 'forty-two' }
|
365
|
-
assert{ m[:x][:y].is_a?(Hash) }
|
366
|
-
assert{ m[:x][:y][:z] == 42.0 }
|
367
|
-
assert{ m.has?('a.b.c') }
|
368
|
-
assert{ m.has?('x.y.z') }
|
369
|
-
assert{ m.has?('A.2') }
|
370
|
-
end
|
371
|
-
|
372
356
|
testing 'that Map#get supports providing a default value in a block' do
|
373
357
|
m = Map.new
|
374
358
|
m.set(:a, :b, :c, 42)
|
@@ -402,6 +386,11 @@ Testing Map do
|
|
402
386
|
assert{ m.apply(defaults) }
|
403
387
|
assert{ m[:array] == [0,1,2] }
|
404
388
|
assert{ m[:hash] =~ {:a => false, :b => true, :c => 42} }
|
389
|
+
|
390
|
+
m = Map.new
|
391
|
+
assert{ m.apply :key => [{:key => :val}] }
|
392
|
+
assert{ m[:key].is_a?(Array) }
|
393
|
+
assert{ m[:key][0].is_a?(Map) }
|
405
394
|
end
|
406
395
|
|
407
396
|
testing 'that maps support depth_first_each' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: map
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.6.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-18 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'description: map kicks the ass'
|
15
15
|
email: ara.t.howard@gmail.com
|