hash_map_hash 1.0.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.
- checksums.yaml +7 -0
- data/lib/hash_map_hash.rb +153 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d9049c119e58ba8638d5d32c15516f58aa58eb0c
|
4
|
+
data.tar.gz: 083f9276f0e2c4d00746f1df32d4fe4f1a7a7072
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d2cf8ed1e41177cc5804554743cd09cd210180c29d321211e23ab5a860a4f41c1625490c4e24fa0cde614bfd0dd3b7f2721db5e8dd1a067aead69af66d79a86
|
7
|
+
data.tar.gz: bdb697f3b6495610d3daf7fb3be981cb3fd3dc913d5c219c6f0b847c4d22b7a1c468ca80d33b4aba00978a79eb1fe90352f5686493504b409b780059c085a2a0
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'deep_dup'
|
2
|
+
|
3
|
+
class HashMapHash
|
4
|
+
attr_reader :mapping
|
5
|
+
|
6
|
+
def initialize(mapping)
|
7
|
+
@mapping = mapping.extend(DeepDup)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Data sample (source_data)
|
11
|
+
#
|
12
|
+
# { 'Contractors' =>
|
13
|
+
# { 'Contractor' =>
|
14
|
+
# [
|
15
|
+
# {
|
16
|
+
# 'Value' => 'FirstAid, Moscow',
|
17
|
+
# 'Role' => 'Payer'
|
18
|
+
# },
|
19
|
+
# {
|
20
|
+
# 'Value' => '84266',
|
21
|
+
# 'OfficialName' => 'FirstAid, Moscow (442, Glow st)',
|
22
|
+
# 'Role' => 'Receiver'
|
23
|
+
# }
|
24
|
+
# ]
|
25
|
+
# },
|
26
|
+
# 'Items' => {
|
27
|
+
# 'NumberOfPositions' => 10
|
28
|
+
# },
|
29
|
+
# 'Total' => 123.45
|
30
|
+
# }
|
31
|
+
#
|
32
|
+
# To get data, we should pass a mapping:
|
33
|
+
#
|
34
|
+
# mapping = {
|
35
|
+
# payer: ['Contractors', 'Contractor', %w(Role Payer), 'Value'],
|
36
|
+
# receiver: ['Contractors', 'Contractor', %w(Role Receiver), 'Value'],
|
37
|
+
# amount: ['Items', 'NumberOfPositions'],
|
38
|
+
# summ: 'Total'
|
39
|
+
# }
|
40
|
+
#
|
41
|
+
# output:
|
42
|
+
# {
|
43
|
+
# payer: 'FirstAid, Moscow',
|
44
|
+
# receiver: '84266',
|
45
|
+
# amount: 10,
|
46
|
+
# summ: 123.45
|
47
|
+
# }
|
48
|
+
def map(source_data)
|
49
|
+
mapping.deep_dup.each_with_object({}) do |(attribute_key, attribute_mapping), result|
|
50
|
+
result[attribute_key] = filtered_deep_fetch source_data, Array(attribute_mapping)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_nested_properties(nested_properties)
|
55
|
+
@mapping.merge! nested_mapping(nested_properties) if nested_properties.any?
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
# data: hash with source data, for example:
|
62
|
+
# {'Contractors' =>
|
63
|
+
# {'Contractor' =>
|
64
|
+
# [
|
65
|
+
# {
|
66
|
+
# 'Value' => 'FirstAid, Moscow',
|
67
|
+
# 'Role' => 'Payer'
|
68
|
+
# },
|
69
|
+
# {
|
70
|
+
# 'Value' => '84266',
|
71
|
+
# 'OfficialName' => 'FirstAid, Moscow (442, Glow st)',
|
72
|
+
# 'Role' => 'Receiver'
|
73
|
+
# }
|
74
|
+
# ]
|
75
|
+
# }
|
76
|
+
# }
|
77
|
+
#
|
78
|
+
# data_mapping: mapping for single attribute
|
79
|
+
# ['Contractors', 'Contractor', %w(Role Payer), 'Value']
|
80
|
+
#
|
81
|
+
# This is a recursive method, it takes one key from mapping and uses it
|
82
|
+
# to walk through data.
|
83
|
+
# Next iteration will receive data and mapping starting from next key.
|
84
|
+
#
|
85
|
+
# Arrays here are filters.
|
86
|
+
# If there is an array in mapping, say, ['Role', 'Payer'], then data on this
|
87
|
+
# level also must be some array.
|
88
|
+
# It will be filtered using #filter_array_of_hashes
|
89
|
+
#
|
90
|
+
def filtered_deep_fetch(data, data_mapping)
|
91
|
+
current_filter = data_mapping.shift
|
92
|
+
return data.fetch(current_filter) if data_mapping.size == 0
|
93
|
+
if current_filter.is_a?(Array)
|
94
|
+
filtered_deep_fetch filter_array_of_hashes(data, current_filter), data_mapping
|
95
|
+
else
|
96
|
+
filtered_deep_fetch data.fetch(current_filter), data_mapping
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# array is an array of hashes, for example:
|
101
|
+
# [
|
102
|
+
# {
|
103
|
+
# 'Value' => 'FirstAid, Moscow',
|
104
|
+
# 'Role' => 'Payer'
|
105
|
+
# },
|
106
|
+
# {
|
107
|
+
# 'Value' => '84266',
|
108
|
+
# 'OfficialName' => 'FirstAid, Moscow (442, Glow st)',
|
109
|
+
# 'Role' => 'Receiver'
|
110
|
+
# }
|
111
|
+
# ]
|
112
|
+
#
|
113
|
+
# keyvalue_filter: key and value for filter, for example ['Role', 'Payer']
|
114
|
+
#
|
115
|
+
# The output is one particular array element:
|
116
|
+
#
|
117
|
+
# {
|
118
|
+
# 'Value' => 'FirstAid, Moscow',
|
119
|
+
# 'Role' => 'Payer'
|
120
|
+
# },
|
121
|
+
def filter_array_of_hashes(data_array, keyvalue_filter)
|
122
|
+
filter_key, filter_value = keyvalue_filter
|
123
|
+
data_array.detect do |element|
|
124
|
+
element[filter_key] == filter_value
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# This metod translates nested_properties to mapping format.
|
129
|
+
# It helps avoValue repeating multiple keys on one level
|
130
|
+
#
|
131
|
+
# Sample:
|
132
|
+
# nested_properties = {
|
133
|
+
# prefix: %w(Contractors Contractor),
|
134
|
+
# filter_key: 'Role',
|
135
|
+
# value_key: 'Value',
|
136
|
+
# keys: {
|
137
|
+
# payer: 'Payer',
|
138
|
+
# receiver: 'Receiver'
|
139
|
+
# }
|
140
|
+
# }
|
141
|
+
#
|
142
|
+
# Output:
|
143
|
+
# {
|
144
|
+
# payer: ['Contractors', 'Contractor', %w(Role Payer), 'Value'],
|
145
|
+
# receiver: ['Contractors', 'Contractor', %w(Role Receiver), 'Value']
|
146
|
+
# }
|
147
|
+
def nested_mapping(nested_properties)
|
148
|
+
nested_properties[:keys].each_with_object({}) do |(key, raw_key), result|
|
149
|
+
result[key] = nested_properties[:prefix] +
|
150
|
+
[[nested_properties[:filter_key], raw_key], nested_properties[:value_key]]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hash_map_hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Denis Peplin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Flatten deeply nested hash and convert keys
|
28
|
+
email: denis.peplin@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/hash_map_hash.rb
|
34
|
+
homepage: http://github.com/denispeplin/hash_map_hash
|
35
|
+
licenses:
|
36
|
+
- MIT
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 2.4.8
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Convert hash to hash using hash map
|
58
|
+
test_files: []
|