nice_hash 1.15.2 → 1.15.3

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.
@@ -0,0 +1,53 @@
1
+ class NiceHash
2
+
3
+ ##################################################
4
+ # Filter the hash supplied and returns only the specified keys
5
+ #
6
+ # @param hash [Hash] The hash we want to filter
7
+ # @param keys [Array] [Symbol] Array of symbols or symbol. Nested keys can be used: 'uno.dos.tres'
8
+ #
9
+ # @return [Hash]
10
+ #
11
+ # @example
12
+ # my_hash = { user: {
13
+ # address: {
14
+ # city: 'Madrid',
15
+ # country: 'Spain'
16
+ # },
17
+ # name: 'Peter',
18
+ # age: 33,
19
+ # customers: [{name: 'Peter', currency: 'Euro'}, {name:'John', currency: 'Euro'}]
20
+ # },
21
+ # customer: true
22
+ # }
23
+ # NiceHash.nice_filter(my_hash, [:'user.address.city', :'customer', :'user.customers.name'])
24
+ # #> {:user => {:address => {:city => "Madrid"}, :customers => [{:name => "Peter"}, {:name => "John"}]}, :customer => true}
25
+ ##################################################
26
+ def self.nice_filter(hash, keys)
27
+ result = {}
28
+ keys = [keys] unless keys.is_a?(Array)
29
+ keys.each do |k|
30
+ kn = k.to_s.split('.')
31
+ if hash.is_a?(Hash) and hash.key?(k)
32
+ if hash[k].is_a?(Hash)
33
+ result[k] = {} unless result.key?(k)
34
+ else
35
+ result[k] = hash[k]
36
+ end
37
+ elsif hash.is_a?(Hash) and hash.key?(kn.first.to_sym)
38
+ keys_nested = []
39
+ keys.grep(/^#{kn.first}\./).each do |k2|
40
+ keys_nested << k2.to_s.gsub(/^#{kn.first}\./,'').to_sym
41
+ end
42
+ result[kn.first.to_sym] = nice_filter(hash[kn.first.to_sym], keys_nested)
43
+ elsif hash.is_a?(Array)
44
+ result = []
45
+ hash.each do |a|
46
+ res = nice_filter(a, keys)
47
+ result << res unless res.empty?
48
+ end
49
+ end
50
+ end
51
+ return result
52
+ end
53
+ end
@@ -0,0 +1,89 @@
1
+ class NiceHash
2
+
3
+ ###########################################################################
4
+ # It will return an array of the keys where we are using string patterns.
5
+ #
6
+ # input:
7
+ # pattern_hash: (Hash) Hash we want to get the pattern_fields
8
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
9
+ # output: (Array)
10
+ # Array of the kind: [ [key], [key, subkey, subkey] ]
11
+ # Each value of the array can be used as parameter for the methods: dig, bury
12
+ # examples:
13
+ # NiceHash.pattern_fields(my_hash)
14
+ # #> [
15
+ # [:address, :correct],
16
+ # [:products, 0, :name],
17
+ # [:products, 0, :price, :correct],
18
+ # [:products, 1, :name],
19
+ # [:products, 1, :price, :correct]
20
+ # ]
21
+ # NiceHash.pattern_fields(my_hash, :correct)
22
+ # #> [
23
+ # [:address],
24
+ # [:products, 0, :name],
25
+ # [:products, 0, :price],
26
+ # [:products, 1, :name],
27
+ # [:products, 1, :price]
28
+ # ]
29
+ # Using it directly on Hash class, pattern_fields(*select_hash_key) (alias: patterns):
30
+ # my_hash.pattern_fields
31
+ # my_hash.pattern_fields(:correct)
32
+ # my_hash.patterns(:correct)
33
+ ###########################################################################
34
+ def NiceHash.pattern_fields(pattern_hash, *select_hash_key)
35
+ pattern_fields = Array.new
36
+
37
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size > 0
38
+ pattern_hash.each { |key, value|
39
+ key = [key]
40
+ if value.kind_of?(Hash)
41
+ if select_hash_key.size == 1 and value.keys.include?(select_hash_key[0])
42
+ value = value[select_hash_key[0]]
43
+ else
44
+ res = NiceHash.pattern_fields(value, *select_hash_key)
45
+ if res.size > 0
46
+ res.each { |r|
47
+ pattern_fields << (r.unshift(key)).flatten
48
+ }
49
+ end
50
+ next
51
+ end
52
+ end
53
+ if value.kind_of?(String)
54
+ if StringPattern.optimistic and value.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
55
+ pattern_fields << key
56
+ end
57
+ elsif value.kind_of?(Symbol)
58
+ if value.to_s.scan(/^!?\d+-?\d*:.+/).size > 0
59
+ pattern_fields << key
60
+ end
61
+ elsif value.kind_of?(Array)
62
+ array_pattern = false
63
+ value.each { |v|
64
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
65
+ pattern_fields << key
66
+ array_pattern = true
67
+ break
68
+ end
69
+ }
70
+ unless array_pattern
71
+ i = 0
72
+ value.each { |v|
73
+ res = NiceHash.pattern_fields(v, *select_hash_key)
74
+ if res.size > 0
75
+ res.each { |r|
76
+ pattern_fields << (r.unshift(i).unshift(key)).flatten
77
+ }
78
+ end
79
+ i += 1
80
+ }
81
+ end
82
+ end
83
+ }
84
+ end
85
+
86
+ return pattern_fields
87
+ end
88
+
89
+ end
@@ -0,0 +1,75 @@
1
+ class NiceHash
2
+
3
+ ###########################################################################
4
+ # It will return an array of the keys where we are using select values of the kind: "value1|value2|value3".
5
+ #
6
+ # input:
7
+ # pattern_hash: (Hash) Hash we want to get the select_fields
8
+ # select_hash_key: (key value) (optional) The key we want to select on the subhashes
9
+ # output: (Array)
10
+ # Array of the kind: [ [key], [key, subkey, subkey] ]
11
+ # Each value of the array can be used as parameter for the methods: dig, bury
12
+ # examples:
13
+ # NiceHash.select_fields(my_hash)
14
+ # #> [[:city, :correct]]
15
+ # NiceHash.select_fields(my_hash, :correct)
16
+ # #> [[:city]]
17
+ # Using it directly on Hash class, select_fields(*select_hash_key):
18
+ # my_hash.select_fields
19
+ # my_hash.select_fields(:correct)
20
+ ###########################################################################
21
+ def NiceHash.select_fields(pattern_hash, *select_hash_key)
22
+ select_fields = Array.new
23
+
24
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size > 0
25
+ pattern_hash.each { |key, value|
26
+ key = [key]
27
+ if value.kind_of?(Hash)
28
+ if select_hash_key.size == 1 and value.keys.include?(select_hash_key[0])
29
+ value = value[select_hash_key[0]]
30
+ else
31
+ res = NiceHash.select_fields(value, *select_hash_key)
32
+ if res.size > 0
33
+ res.each { |r|
34
+ select_fields << (r.unshift(key)).flatten
35
+ }
36
+ end
37
+ next
38
+ end
39
+ end
40
+ if value.kind_of?(String)
41
+ if StringPattern.optimistic and value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size > 0
42
+ select_fields << key
43
+ end
44
+ elsif value.kind_of?(Symbol)
45
+ if value.to_s.scan(/^([\w\s\-]+\|)+[\w\s\-]+$/).size > 0
46
+ select_fields << key
47
+ end
48
+ elsif value.kind_of?(Array)
49
+ array_pattern = false
50
+ value.each { |v|
51
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
52
+ array_pattern = true
53
+ break
54
+ end
55
+ }
56
+ unless array_pattern
57
+ i = 0
58
+ value.each { |v|
59
+ res = NiceHash.select_fields(v, *select_hash_key)
60
+ if res.size > 0
61
+ res.each { |r|
62
+ select_fields << (r.unshift(i).unshift(key)).flatten
63
+ }
64
+ end
65
+ i += 1
66
+ }
67
+ end
68
+ end
69
+ }
70
+ end
71
+
72
+ return select_fields
73
+ end
74
+
75
+ end
@@ -0,0 +1,56 @@
1
+ class NiceHash
2
+ ###########################################################################
3
+ # It will filter the hash by the key specified on select_hash_key.
4
+ # In case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
5
+ #
6
+ # input:
7
+ # pattern_hash: (Hash) Hash we want to select specific keys
8
+ # select_hash_key: (key value) The key we want to select on the subhashes
9
+ # output: (Hash)
10
+ # The same hash but in case a subhash specified on a value it will be selected only the value of the key specified on select_hash_key
11
+ # example:
12
+ # new_hash = NiceHash.select_key(my_hash, :wrong)
13
+ # #> {:name=>"Peter", :address=>"\#$$$$$", :city=>"Germany", :products=> [{:name=>:"10:Ln", :price=>"-20"}, {:name=>:"10:Ln", :price=>"-20"}]}
14
+ # Using it directly on Hash class, select_key(select_hash_key):
15
+ # new_hash = my_hash.select_key(:wrong)
16
+ ###########################################################################
17
+ def NiceHash.select_key(pattern_hash, select_hash_key)
18
+ hashv = Hash.new()
19
+
20
+ if pattern_hash.kind_of?(Hash) and pattern_hash.size > 0
21
+ pattern_hash.each { |key, value|
22
+ if value.kind_of?(Hash)
23
+ if value.keys.include?(select_hash_key)
24
+ value = value[select_hash_key]
25
+ else
26
+ value = NiceHash.select_key(value, select_hash_key)
27
+ end
28
+ end
29
+ if value.kind_of?(Array)
30
+ array_pattern = false
31
+ value.each { |v|
32
+ if (v.kind_of?(String) or v.kind_of?(Symbol)) and StringPattern.analyze(v, silent: true).kind_of?(StringPattern::Pattern)
33
+ hashv[key] = value
34
+ array_pattern = true
35
+ break
36
+ end
37
+ }
38
+ unless array_pattern
39
+ value_ret = Array.new
40
+ value.each { |v|
41
+ ret = NiceHash.select_key(v, select_hash_key)
42
+ value_ret << ret
43
+ }
44
+ hashv[key] = value_ret
45
+ end
46
+ else
47
+ hashv[key] = value
48
+ end
49
+ }
50
+ else
51
+ return pattern_hash
52
+ end
53
+ return hashv
54
+ end
55
+
56
+ end
@@ -0,0 +1,54 @@
1
+ class NiceHash
2
+ ##################################################
3
+ # sets the supplied value on the supplied nested key
4
+ #
5
+ # @param hash [Hash] The hash we want
6
+ # @param nested_key [Hash] [String] String with the nested key: 'uno.dos.tres' or a hash { uno: {dos: :tres} }
7
+ # @param value [] value to set
8
+ #
9
+ # @return [Hash]
10
+ #
11
+ # @example
12
+ # my_hash = { user: {
13
+ # address: {
14
+ # city: 'Madrid',
15
+ # country: 'Spain'
16
+ # },
17
+ # name: 'Peter',
18
+ # age: 33
19
+ # },
20
+ # customer: true
21
+ # }
22
+ # NiceHash.set_nested(my_hash, 'user.address.city', 'Barcelona')
23
+ # #>{:user=>{:address=>{:city=>'Barcelona', :country=>"Spain"}, :name=>"Peter", :age=>33}, :customer=>true}
24
+ ##################################################
25
+ def self.set_nested(hash, nested_key, value, only_if_exist = false)
26
+ nested_key = transtring(nested_key)
27
+ keys = nested_key.split(".")
28
+ if keys.size == 1
29
+ hash[nested_key.to_sym] = value unless only_if_exist and !hash.key?(nested_key.to_sym)
30
+ else
31
+ exist = true
32
+ if only_if_exist
33
+ ht = hash.deep_copy
34
+ keys.each do |k|
35
+ unless ht.key?(k.to_sym)
36
+ exist = false
37
+ break
38
+ end
39
+ ht = ht[k.to_sym]
40
+ end
41
+ end
42
+ if !only_if_exist or (only_if_exist and exist)
43
+ if value.is_a?(String)
44
+ eval("hash.#{nested_key}='#{value}'")
45
+ else
46
+ #todo: consider other kind of objects apart of strings
47
+ eval("hash.#{nested_key}=#{value}")
48
+ end
49
+ end
50
+ end
51
+ return hash
52
+ end
53
+
54
+ end
@@ -0,0 +1,99 @@
1
+ class NiceHash
2
+ ###########################################################################
3
+ # It will search for the keys supplied and it will set the value specified
4
+ #
5
+ # input:
6
+ # hash_array: (Hash/Array) Hash/Array we want to search on
7
+ # hash_values: (Hash) Hash that contains the keys and values to set
8
+ # output: (Hash/Array)
9
+ # The same hash/array but with the values we specifed changed
10
+ # example:
11
+ # new_hash = NiceHash.set_values(my_hash, {city: 'London', price: '1000'})
12
+ # #> {:name=>"Peter", :address=>"\#$$$$$", :city=>"London", :products=> [{:name=>:"10:Ln", :price=>"1000"}, {:name=>:"10:Ln", :price=>"1000"}]}
13
+ # Using it directly on Hash class, set_values(hash_values):
14
+ # new_hash = my_hash.set_values({city: 'London', price: '1000'})
15
+ # Setting specific nested keys
16
+ # new_hash = my_hash.set_values({'data.lab.products.price': 75, 'data.lab.beep': false})
17
+ ###########################################################################
18
+ def NiceHash.set_values(hash_array, hash_values)
19
+ hashv = Hash.new()
20
+ if hash_array.is_a?(Hash) and hash_array.size > 0
21
+ #for the case same_values on hash_values
22
+ #fex: ({pwd1: 'aaaa', pwd2: 'bbbbb', uno: 1}).set_values({[:pwd1, :pwd2]=>:'1-10:n'})
23
+ # should return : {[:pwd1, :pwd2]=>:'1-10:n', uno: 1}
24
+ #todo: it doesn't work for all cases, just simple one
25
+ if hash_values.is_a?(Hash) and hash_values.keys.flatten.size != hash_values.keys.size
26
+ hash_values.each do |k,v|
27
+ if k.is_a?(Array)
28
+ k.each do |kvk|
29
+ if hash_array.key?(kvk)
30
+ hash_array[kvk] = hash_values[k]
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ hash_array.each do |k, v|
38
+ #for the case of using same_values: [:pwd1, :pwd2] => :'10:N' and supply hash_values: pwd1: 'a', pwd2: 'b'
39
+ #instead of [:pwd1,:pwd2]=>'a'
40
+ same_values_key_done = false
41
+ if k.is_a?(Array)
42
+ #todo: we are treating here only a simple case, consider to add also nested keys, array of values...
43
+ k.each do |kvk|
44
+ if hash_values.keys.include?(kvk)
45
+ hashv[k] = hash_values[kvk]
46
+ same_values_key_done = true
47
+ end
48
+ end
49
+ end
50
+ unless same_values_key_done
51
+ if hash_values.keys.include?(k)
52
+ hashv[k] = hash_values[k]
53
+ elsif v.is_a?(Array)
54
+ if hash_values.has_rkey?('\.') # the kind of 'uno.dos.tres'
55
+ new_hash_values = {}
56
+ hash_values.each do |kk,vv|
57
+ if kk.to_s.match?(/^#{k}\./)
58
+ kk = kk.to_s.gsub(/^#{k}\./, '').to_sym
59
+ new_hash_values[kk] = vv
60
+ end
61
+ end
62
+ hashv[k] = NiceHash.set_values(v, new_hash_values)
63
+ else
64
+ hashv[k] = NiceHash.set_values(v, hash_values)
65
+ end
66
+ elsif v.is_a?(Hash)
67
+ if hash_values.has_rkey?('\.') # the kind of 'uno.dos.tres'
68
+ new_hash_values = {}
69
+ hash_values.each do |kk,vv|
70
+ if kk.to_s.match?(/^#{k}\./)
71
+ kk = kk.to_s.gsub(/^#{k}\./, '').to_sym
72
+ new_hash_values[kk] = vv
73
+ end
74
+ end
75
+ hashv[k] = NiceHash.set_values(v, new_hash_values)
76
+ else
77
+ hashv[k] = NiceHash.set_values(v, hash_values)
78
+ end
79
+ else
80
+ hashv[k] = v
81
+ end
82
+ end
83
+ end
84
+ hash_values.each do |k, v|
85
+ hashv = NiceHash.set_nested(hashv, k, v, true) if k.is_a?(Hash)
86
+ end
87
+ return hashv
88
+ elsif hash_array.is_a?(Array) and hash_array.size > 0
89
+ hashv = Array.new
90
+ hash_array.each do |r|
91
+ hashv << NiceHash.set_values(r, hash_values)
92
+ end
93
+ return hashv
94
+ else
95
+ return hash_array
96
+ end
97
+ end
98
+
99
+ end
@@ -0,0 +1,32 @@
1
+ class NiceHash
2
+ ##################################################
3
+ # Translate a hash of hashes into a string separted by .
4
+ #
5
+ # @param hash [Hash] The hash we want to translate
6
+ #
7
+ # @return [String]
8
+ #
9
+ # @example
10
+ # my_hash = { uno: {dos: :tres} }
11
+ # NiceHash.transtring(my_hash)
12
+ # #>"uno.dos.tres"
13
+ ##################################################
14
+ def self.transtring(hash)
15
+ keys = []
16
+ if hash.is_a?(Hash)
17
+ hash.each do |k, v|
18
+ if v.is_a?(Hash)
19
+ keys << k
20
+ keys << transtring(v)
21
+ else
22
+ keys << k
23
+ keys << v
24
+ end
25
+ end
26
+ else
27
+ keys << hash
28
+ end
29
+ return keys.join(".")
30
+ end
31
+
32
+ end