array_collection 0.2.8 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +26 -24
- data/lib/array_collection/array_components/data_handling.rb +26 -0
- data/lib/array_collection/array_components/filtering.rb +27 -0
- data/lib/array_collection/array_components/joining.rb +83 -0
- data/lib/array_collection/array_components/key_filtering.rb +23 -0
- data/lib/array_collection/array_components/mapping.rb +15 -0
- data/lib/array_collection/collect.rb +76 -41
- data/lib/array_collection/collection_array.rb +10 -126
- data/lib/array_collection/json_parser.rb +42 -0
- data/lib/array_collection/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef33c3e653a6e11b9d4c92b2524b71f772cdb1e49399ab6d9da1138af9d08612
|
4
|
+
data.tar.gz: 4c029f0f9e11c739b26737bb7db34573221c377e76958b872a3813f87dab7810
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6b3624550f8f9e00ddffcf950b198fe4f7bfc4c544ae258d9d4c2da1eac0a3ecfe4f09b05cbeff050b047d25d9ab2449926473417ceb63bd4a79aa762ac0d6f
|
7
|
+
data.tar.gz: 89011dea94eb965e5cdcadb013b92a388b5f3ed5a3fcd459c2bfc28a24a5cfef3c1af34099d92b3fca20511b379e99789bb4ea40e2afd59a3baea6b556fac1d9
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,52 +2,54 @@
|
|
2
2
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
4
4
|
|
5
|
-
## [0.
|
5
|
+
## [0.3.1](https://github.com/WailanTirajoh/ruby_collection/compare/v0.3.0...v0.3.1) (2024-03-31)
|
6
6
|
|
7
7
|
|
8
8
|
### Bug Fixes
|
9
9
|
|
10
|
-
* **
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
## [0.2.14](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.13...v0.2.14) (2024-03-26)
|
15
|
-
|
10
|
+
* **lint:** use described_class ([afba961](https://github.com/WailanTirajoh/ruby_collection/commit/afba961936538978109642db7c582a5746bbd5ea))
|
16
11
|
|
17
12
|
|
18
|
-
|
13
|
+
### Features
|
19
14
|
|
15
|
+
* **contional:** #unless ([#12](https://github.com/WailanTirajoh/ruby_collection/issues/12)) ([5d141b3](https://github.com/WailanTirajoh/ruby_collection/commit/5d141b3aa05eef1d5649ae1cd3aae14215ec5e17))
|
16
|
+
* **join:** cross join ([#14](https://github.com/WailanTirajoh/ruby_collection/issues/14)) ([9657d6b](https://github.com/WailanTirajoh/ruby_collection/commit/9657d6bab25af6d00b329bc6d72bc0b560846b5a))
|
17
|
+
* **json:** allow string keys as input ([#10](https://github.com/WailanTirajoh/ruby_collection/issues/10)) ([4b47b1d](https://github.com/WailanTirajoh/ruby_collection/commit/4b47b1de2b5f3a7f0d35186321ecaa8adc4048bb))
|
20
18
|
|
21
19
|
|
22
|
-
## [0.2.12](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.11...v0.2.12) (2024-03-26)
|
23
20
|
|
21
|
+
# [0.3.0](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.8...v0.3.0) (2024-03-29)
|
24
22
|
|
25
23
|
|
26
|
-
|
24
|
+
### Features
|
27
25
|
|
26
|
+
* **collect:** count ([7620a62](https://github.com/WailanTirajoh/ruby_collection/commit/7620a62bb6260e36210290a73f4083db533107b3))
|
27
|
+
* **collect:** uniq ([59a5c53](https://github.com/WailanTirajoh/ruby_collection/commit/59a5c53f2de89ea1d3099c726e7abaffffcf78bc))
|
28
|
+
* **collect:** uniq with block ([5fab50e](https://github.com/WailanTirajoh/ruby_collection/commit/5fab50e82775f67397cc0257aa1333c88483c30f))
|
29
|
+
* **rubocop-performance:** init & fix rubocop perf ([fa91115](https://github.com/WailanTirajoh/ruby_collection/commit/fa91115f40a5179957f5361d34a9d378c6bd7a0a))
|
28
30
|
|
29
31
|
|
30
|
-
## [0.2.10](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.9...v0.2.10) (2024-03-26)
|
31
32
|
|
33
|
+
## [0.2.8](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.14...v0.2.8) (2024-03-26)
|
32
34
|
|
33
35
|
### Bug Fixes
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
- **changelog:** bump changlog ([b50d44a](https://github.com/WailanTirajoh/ruby_collection/commit/b50d44ad655287ecbe0b934341d0a031f12e7cac))
|
38
|
+
- **gem:** remove required mfa ([7b4b9c4](https://github.com/WailanTirajoh/ruby_collection/commit/7b4b9c432002ff4381da0004d3ad4d6912b8b2d8))
|
39
|
+
- **gem:** remove required mfa ([d342636](https://github.com/WailanTirajoh/ruby_collection/commit/d3426369e6f1dff96abc568689fc9ec4381967f1))
|
40
|
+
- **lint:** Lintfix ([be99af7](https://github.com/WailanTirajoh/ruby_collection/commit/be99af72b9f3a2cfadad224aff191aafb48a6d45))
|
38
41
|
|
39
42
|
### Features
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
- **collect:** add left_join, right_join, full_join ([bca2af5](https://github.com/WailanTirajoh/ruby_collection/commit/bca2af5ec5e9b078fb7c75155ae0e1f79e8e1732))
|
45
|
+
- **collection:** add sort, append, prepend, map and test chainable collection ([8084fc9](https://github.com/WailanTirajoh/ruby_collection/commit/8084fc966b2a3540c3e5f8935b56d795d8bf8b69))
|
46
|
+
- **collection:** first initial collection & array fn ([2009281](https://github.com/WailanTirajoh/ruby_collection/commit/2009281a2d53d8ffa4a0090fd4e363329ac0f4ed))
|
47
|
+
- **collection:** first initial collection & array fn ([04efd77](https://github.com/WailanTirajoh/ruby_collection/commit/04efd77f32bae72e1ad53391744bbfde12123754))
|
48
|
+
- **data:** data accessor based on dot notation ([92efb9e](https://github.com/WailanTirajoh/ruby_collection/commit/92efb9e48f6dbeeb72c3f2bc1090bd4cd9f903c2))
|
49
|
+
- **diff:** add diff & refactor array spec ([d0e3a66](https://github.com/WailanTirajoh/ruby_collection/commit/d0e3a66c8bd2d6d4f7ba706537b01e18929a3d51))
|
50
|
+
- **helper:** add collect helper ([13c4efb](https://github.com/WailanTirajoh/ruby_collection/commit/13c4efbbc481960227f361208818471a197df752))
|
51
|
+
- **join:** inner join ([d1f011b](https://github.com/WailanTirajoh/ruby_collection/commit/d1f011b76560ad26fdecdef1c01cdc7291cbac6e))
|
52
|
+
- **utils:** add when, only, except ([77da9e8](https://github.com/WailanTirajoh/ruby_collection/commit/77da9e848ae60b771f24cf623b73df85f80b1eea))
|
51
53
|
|
52
54
|
## [0.1.0] - 2024-03-15
|
53
55
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArrayCollection
|
4
|
+
module ArrayComponents
|
5
|
+
module DataHandling # rubocop:disable Style/Documentation
|
6
|
+
def wrap(value)
|
7
|
+
return [] if value.nil?
|
8
|
+
return value if value.is_a?(Array)
|
9
|
+
|
10
|
+
[value]
|
11
|
+
end
|
12
|
+
|
13
|
+
def append(array, *elements)
|
14
|
+
array + elements
|
15
|
+
end
|
16
|
+
|
17
|
+
def prepend(array, *elements)
|
18
|
+
elements + array
|
19
|
+
end
|
20
|
+
|
21
|
+
def diff(array1, array2)
|
22
|
+
(array1 - array2) | (array2 - array1)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArrayCollection
|
4
|
+
module ArrayComponents
|
5
|
+
module Filtering # rubocop:disable Style/Documentation
|
6
|
+
def filter(array, &block)
|
7
|
+
array.select(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def where(array, *args)
|
11
|
+
if args.size == 2
|
12
|
+
key, value = args
|
13
|
+
array.select { |item| item[key] == value }
|
14
|
+
elsif args.size == 3
|
15
|
+
key, operator, value = args
|
16
|
+
array.select { |item| ArrayCollection::CollectionFilter.apply_operator(operator, item[key], value) }
|
17
|
+
else
|
18
|
+
raise ArgumentError, "Invalid number of arguments"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def where_not_nil(array)
|
23
|
+
array.compact
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "array_collection/collection_filter"
|
4
|
+
|
5
|
+
module ArrayCollection
|
6
|
+
module ArrayComponents
|
7
|
+
# Module containing methods for joining arrays
|
8
|
+
module Joining
|
9
|
+
def join(array1, array2, key1, key2)
|
10
|
+
inner_join(array1, array2, key1, key2)
|
11
|
+
end
|
12
|
+
|
13
|
+
def inner_join(array1, array2, key1, key2)
|
14
|
+
array1.reject do |item1|
|
15
|
+
matching_items = array2.select { |item2| item1[key1] == item2[key2] }
|
16
|
+
matching_items.each { |matched_item| item1.merge!(matched_item) }
|
17
|
+
matching_items.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def left_join(array1, array2, key1, key2)
|
22
|
+
return array1 if array2.count.zero?
|
23
|
+
|
24
|
+
right_index = build_index(array2, key2)
|
25
|
+
|
26
|
+
result = []
|
27
|
+
array1.each do |left_item|
|
28
|
+
right_items = right_index[left_item[key1]] || [nil_attributes(array2)]
|
29
|
+
merge_items(result, left_item, right_items)
|
30
|
+
end
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def right_join(array1, array2, key1, key2)
|
35
|
+
left_index = build_index(array1, key1)
|
36
|
+
|
37
|
+
result = []
|
38
|
+
array2.each do |right_item|
|
39
|
+
left_items = left_index[right_item[key2]] || [nil_attributes(array1)]
|
40
|
+
merge_items(result, right_item, left_items)
|
41
|
+
end
|
42
|
+
result
|
43
|
+
end
|
44
|
+
|
45
|
+
def full_join(array1, array2, key1, key2)
|
46
|
+
left_join_result = left_join(array1, array2, key1, key2)
|
47
|
+
right_join_result = right_join(array1, array2, key1, key2)
|
48
|
+
|
49
|
+
left_join_result.concat(right_join_result).uniq
|
50
|
+
end
|
51
|
+
|
52
|
+
def full_outter_join(array1, array2, key1, key2)
|
53
|
+
full_join(array1, array2, key1, key2)
|
54
|
+
end
|
55
|
+
|
56
|
+
def cross_join(array1, array2)
|
57
|
+
return cross_join_hashes(array1, array2) if array1.all?(Hash) && array2.all?(Hash)
|
58
|
+
|
59
|
+
array1.product(array2)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def cross_join_hashes(array1, array2)
|
65
|
+
array1.flat_map { |hash1| array2.map { |hash2| hash1.merge(hash2) } }
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_index(array, key)
|
69
|
+
array.group_by { |item| item[key] }
|
70
|
+
end
|
71
|
+
|
72
|
+
def merge_items(result, left_item, right_items)
|
73
|
+
right_items.each do |right_item|
|
74
|
+
result << left_item.merge(right_item)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def nil_attributes(array)
|
79
|
+
array.first.keys.each_with_object({}) { |key, hash| hash[key] = nil }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArrayCollection
|
4
|
+
module ArrayComponents
|
5
|
+
module KeyFiltering # rubocop:disable Style/Documentation
|
6
|
+
def key_by(records, key)
|
7
|
+
records.to_h { |record| [record[key].to_s, yield(record)] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def except(array, *keys)
|
11
|
+
raise ArgumentError, "Empty key list" if keys.empty?
|
12
|
+
|
13
|
+
array.map { |hash| hash.except(*keys) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def only(array, *keys)
|
17
|
+
raise ArgumentError, "Empty key list" if keys.empty?
|
18
|
+
|
19
|
+
array.map { |hash| hash.select { |k, _| keys.include?(k) } }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArrayCollection
|
4
|
+
module ArrayComponents
|
5
|
+
module Mapping # rubocop:disable Style/Documentation
|
6
|
+
def map(array, &block)
|
7
|
+
array.map(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
def map_with_keys(hash, &block)
|
11
|
+
hash.transform_values(&block)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -2,30 +2,24 @@
|
|
2
2
|
|
3
3
|
require_relative "collection_array"
|
4
4
|
require_relative "hooks"
|
5
|
+
require_relative "json_parser"
|
5
6
|
|
6
7
|
module ArrayCollection
|
7
8
|
# Set of chainable collections
|
8
|
-
class Collect
|
9
|
+
class Collect # rubocop:disable Metrics/ClassLength
|
9
10
|
extend ArrayCollection::Hooks
|
10
11
|
|
11
12
|
def initialize(items)
|
12
|
-
|
13
|
+
parsed_hash = parse(items)
|
14
|
+
@items, @is_json = get_arrayable_items(parsed_hash)
|
13
15
|
end
|
14
16
|
|
15
17
|
def all
|
16
|
-
@items
|
18
|
+
parse_output(@items)
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def where(key, *args)
|
24
|
-
self.class.new(ArrayCollection::CollectionArray.where(@items, key, *args))
|
25
|
-
end
|
26
|
-
|
27
|
-
def where_not_nil
|
28
|
-
self.class.new(ArrayCollection::CollectionArray.where_not_nil(@items))
|
21
|
+
def count(&block)
|
22
|
+
@items.count(&block)
|
29
23
|
end
|
30
24
|
|
31
25
|
def index_of(value)
|
@@ -33,73 +27,95 @@ module ArrayCollection
|
|
33
27
|
end
|
34
28
|
|
35
29
|
def key_by(key, &block)
|
36
|
-
ArrayCollection::CollectionArray.key_by(@items, key, &block)
|
30
|
+
ArrayCollection::CollectionArray.key_by(@items, key.to_sym, &block)
|
37
31
|
end
|
38
32
|
|
39
|
-
def
|
40
|
-
self
|
41
|
-
end
|
33
|
+
def when(boolean)
|
34
|
+
return self if boolean == false
|
42
35
|
|
43
|
-
|
44
|
-
self.class.new(@items.sort(&block).reverse)
|
36
|
+
yield(self)
|
45
37
|
end
|
46
38
|
|
47
|
-
def
|
48
|
-
self
|
39
|
+
def unless(boolean)
|
40
|
+
return self if boolean == true
|
41
|
+
|
42
|
+
yield(self)
|
49
43
|
end
|
50
44
|
|
51
45
|
def append(value)
|
52
|
-
|
46
|
+
clone(ArrayCollection::CollectionArray.append(@items, value))
|
53
47
|
end
|
54
48
|
|
55
49
|
def prepend(value)
|
56
|
-
|
50
|
+
clone(ArrayCollection::CollectionArray.prepend(@items, value))
|
57
51
|
end
|
58
52
|
|
59
|
-
def
|
60
|
-
|
53
|
+
def diff(items)
|
54
|
+
clone(ArrayCollection::CollectionArray.diff(@items, items))
|
61
55
|
end
|
62
56
|
|
63
|
-
def
|
64
|
-
|
57
|
+
def filter(&block)
|
58
|
+
clone(ArrayCollection::CollectionArray.filter(@items, &block))
|
59
|
+
end
|
65
60
|
|
66
|
-
|
61
|
+
def where(key, *args)
|
62
|
+
clone(ArrayCollection::CollectionArray.where(@items, key, *args))
|
63
|
+
end
|
64
|
+
|
65
|
+
def where_not_nil
|
66
|
+
clone(ArrayCollection::CollectionArray.where_not_nil(@items))
|
67
|
+
end
|
68
|
+
|
69
|
+
def uniq
|
70
|
+
clone(@items.uniq)
|
67
71
|
end
|
68
72
|
|
69
73
|
def only(*keys)
|
70
|
-
|
74
|
+
clone(ArrayCollection::CollectionArray.only(@items, *keys.map(&:to_sym)))
|
71
75
|
end
|
72
76
|
|
73
77
|
def except(*keys)
|
74
|
-
|
78
|
+
clone(ArrayCollection::CollectionArray.except(@items, *keys.map(&:to_sym)))
|
75
79
|
end
|
76
80
|
|
77
|
-
def
|
78
|
-
|
81
|
+
def map(&block)
|
82
|
+
clone(ArrayCollection::CollectionArray.map(@items, &block))
|
83
|
+
end
|
84
|
+
|
85
|
+
def sort(&block)
|
86
|
+
clone(@items.sort(&block))
|
87
|
+
end
|
88
|
+
|
89
|
+
def sort_desc(&block)
|
90
|
+
clone(@items.sort(&block).reverse)
|
91
|
+
end
|
92
|
+
|
93
|
+
def sort_by_key(key)
|
94
|
+
clone(@items.sort_by { |item| item[key.to_sym] })
|
79
95
|
end
|
80
96
|
|
81
97
|
def inner_join(items, left_key, right_key)
|
82
|
-
|
83
|
-
right_key))
|
98
|
+
clone(ArrayCollection::CollectionArray.inner_join(@items, get_arrayable_items(items), left_key, right_key))
|
84
99
|
end
|
85
100
|
|
86
101
|
def left_join(items, left_key, right_key)
|
87
|
-
|
88
|
-
right_key))
|
102
|
+
clone(ArrayCollection::CollectionArray.left_join(@items, get_arrayable_items(items), left_key, right_key))
|
89
103
|
end
|
90
104
|
|
91
105
|
def right_join(items, left_key, right_key)
|
92
|
-
|
93
|
-
right_key))
|
106
|
+
clone(ArrayCollection::CollectionArray.right_join(@items, get_arrayable_items(items), left_key, right_key))
|
94
107
|
end
|
95
108
|
|
96
109
|
def full_join(items, left_key, right_key)
|
97
|
-
|
98
|
-
right_key))
|
110
|
+
clone(ArrayCollection::CollectionArray.full_join(@items, get_arrayable_items(items), left_key, right_key))
|
99
111
|
end
|
100
112
|
|
101
113
|
private
|
102
114
|
|
115
|
+
def clone(result)
|
116
|
+
self.class.new(parse_output(result))
|
117
|
+
end
|
118
|
+
|
103
119
|
def get_arrayable_items(items)
|
104
120
|
case items
|
105
121
|
when Array
|
@@ -112,7 +128,26 @@ module ArrayCollection
|
|
112
128
|
end
|
113
129
|
|
114
130
|
def check_hash_item
|
115
|
-
raise ArgumentError, "Input must be an array of hashes" unless @items.all?
|
131
|
+
raise ArgumentError, "Input must be an array of hashes" unless @items.all?(Hash)
|
132
|
+
end
|
133
|
+
|
134
|
+
def json?
|
135
|
+
@is_json
|
136
|
+
end
|
137
|
+
|
138
|
+
def parse(items)
|
139
|
+
is_json = ArrayCollection::JsonParser.json_like?(items)
|
140
|
+
result = is_json ? ArrayCollection::JsonParser.parse_to_hash(items) : items
|
141
|
+
|
142
|
+
[get_arrayable_items(result), is_json]
|
143
|
+
end
|
144
|
+
|
145
|
+
def parse_output(items)
|
146
|
+
if json?
|
147
|
+
ArrayCollection::JsonParser.parse_to_json(items)
|
148
|
+
else
|
149
|
+
items
|
150
|
+
end
|
116
151
|
end
|
117
152
|
|
118
153
|
# Hooks
|
@@ -1,136 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
3
|
+
require_relative "array_components/filtering"
|
4
|
+
require_relative "array_components/mapping"
|
5
|
+
require_relative "array_components/data_handling"
|
6
|
+
require_relative "array_components/key_filtering"
|
7
|
+
require_relative "array_components/joining"
|
4
8
|
|
5
9
|
module ArrayCollection
|
6
10
|
# Sets of array utilities methods
|
7
11
|
class CollectionArray
|
8
12
|
class << self
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
if args.size == 2
|
15
|
-
key, value = args
|
16
|
-
array.select { |item| item[key] == value }
|
17
|
-
elsif args.size == 3
|
18
|
-
key, operator, value = args
|
19
|
-
array.select { |item| ArrayCollection::CollectionFilter.apply_operator(operator, item[key], value) }
|
20
|
-
else
|
21
|
-
raise ArgumentError, "Invalid number of arguments"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def where_not_nil(array)
|
26
|
-
array.compact
|
27
|
-
end
|
28
|
-
|
29
|
-
def wrap(value)
|
30
|
-
return [] if value.nil?
|
31
|
-
return value if value.is_a?(Array)
|
32
|
-
|
33
|
-
[value]
|
34
|
-
end
|
35
|
-
|
36
|
-
def append(array, *elements)
|
37
|
-
array + elements
|
38
|
-
end
|
39
|
-
|
40
|
-
def prepend(array, *elements)
|
41
|
-
elements + array
|
42
|
-
end
|
43
|
-
|
44
|
-
def map(array, &block)
|
45
|
-
array.map(&block)
|
46
|
-
end
|
47
|
-
|
48
|
-
def map_with_keys(hash, &block)
|
49
|
-
hash.transform_values(&block)
|
50
|
-
end
|
51
|
-
|
52
|
-
def key_by(records, key)
|
53
|
-
records.to_h { |record| [record[key].to_s, yield(record)] }
|
54
|
-
end
|
55
|
-
|
56
|
-
def except(array, *keys)
|
57
|
-
raise ArgumentError, "Empty key list" if keys.empty?
|
58
|
-
|
59
|
-
array.map { |hash| hash.except(*keys) }
|
60
|
-
end
|
61
|
-
|
62
|
-
def only(array, *keys)
|
63
|
-
raise ArgumentError, "Empty key list" if keys.empty?
|
64
|
-
|
65
|
-
array.map { |hash| hash.select { |k, _| keys.include?(k) } }
|
66
|
-
end
|
67
|
-
|
68
|
-
def diff(array1, array2)
|
69
|
-
(array1 - array2) | (array2 - array1)
|
70
|
-
end
|
71
|
-
|
72
|
-
def join(array1, array2, key1, key2)
|
73
|
-
inner_join(array1, array2, key1, key2)
|
74
|
-
end
|
75
|
-
|
76
|
-
def inner_join(array1, array2, key1, key2)
|
77
|
-
array1.reject do |item1|
|
78
|
-
matching_items = array2.select { |item2| item1[key1] == item2[key2] }
|
79
|
-
matching_items.each { |matched_item| item1.merge!(matched_item) }
|
80
|
-
matching_items.empty?
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def left_join(array1, array2, key1, key2)
|
85
|
-
return array1 if array2.count.zero?
|
86
|
-
|
87
|
-
right_index = build_index(array2, key2)
|
88
|
-
|
89
|
-
result = []
|
90
|
-
array1.each do |left_item|
|
91
|
-
right_items = right_index[left_item[key1]] || [nil_attributes(array2)]
|
92
|
-
merge_items(result, left_item, right_items)
|
93
|
-
end
|
94
|
-
result
|
95
|
-
end
|
96
|
-
|
97
|
-
def right_join(array1, array2, key1, key2)
|
98
|
-
left_index = build_index(array1, key1)
|
99
|
-
|
100
|
-
result = []
|
101
|
-
array2.each do |right_item|
|
102
|
-
left_items = left_index[right_item[key2]] || [nil_attributes(array1)]
|
103
|
-
merge_items(result, right_item, left_items)
|
104
|
-
end
|
105
|
-
result
|
106
|
-
end
|
107
|
-
|
108
|
-
def full_join(array1, array2, key1, key2)
|
109
|
-
left_join_result = left_join(array1, array2, key1, key2)
|
110
|
-
right_join_result = right_join(array1, array2, key1, key2)
|
111
|
-
|
112
|
-
left_join_result.concat(right_join_result).uniq
|
113
|
-
end
|
114
|
-
|
115
|
-
def full_outter_join(array1, array2, key1, key2)
|
116
|
-
full_join(array1, array2, key1, key2)
|
117
|
-
end
|
118
|
-
|
119
|
-
private
|
120
|
-
|
121
|
-
def build_index(array, key)
|
122
|
-
array.group_by { |item| item[key] }
|
123
|
-
end
|
124
|
-
|
125
|
-
def merge_items(result, left_item, right_items)
|
126
|
-
right_items.each do |right_item|
|
127
|
-
result << left_item.merge(right_item)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def nil_attributes(array)
|
132
|
-
array.first.keys.each_with_object({}) { |key, hash| hash[key] = nil }
|
133
|
-
end
|
13
|
+
include ArrayCollection::ArrayComponents::Filtering
|
14
|
+
include ArrayCollection::ArrayComponents::Mapping
|
15
|
+
include ArrayCollection::ArrayComponents::DataHandling
|
16
|
+
include ArrayCollection::ArrayComponents::KeyFiltering
|
17
|
+
include ArrayCollection::ArrayComponents::Joining
|
134
18
|
end
|
135
19
|
end
|
136
20
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ArrayCollection
|
4
|
+
# JSON Parser for collection
|
5
|
+
class JsonParser
|
6
|
+
class << self
|
7
|
+
def json_like?(input)
|
8
|
+
return false if input.nil? || input.count.zero?
|
9
|
+
|
10
|
+
hash = input[0]
|
11
|
+
hash.is_a?(Hash) && hash.keys.all?(String)
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_to_hash(json_like)
|
15
|
+
json_like.map { |hash| deep_string_to_symbol(hash) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_to_json(hashes)
|
19
|
+
hashes.map { |hash| deep_stringify_keys(hash) }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def deep_string_to_symbol(hash)
|
25
|
+
return hash unless hash.is_a?(Hash)
|
26
|
+
|
27
|
+
hash.each_with_object({}) do |(key, value), result|
|
28
|
+
new_key = key.is_a?(String) ? key.to_sym : key
|
29
|
+
result[new_key] = deep_string_to_symbol(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def deep_stringify_keys(hash)
|
34
|
+
hash.each_with_object({}) do |(key, value), result|
|
35
|
+
new_key = key.to_s
|
36
|
+
new_value = value.is_a?(Hash) ? deep_stringify_keys(value) : value
|
37
|
+
result[new_key] = new_value
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: array_collection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wailan Tirajoh
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-03-
|
11
|
+
date: 2024-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Write a longer description or delete this line.
|
14
14
|
email:
|
@@ -28,12 +28,18 @@ files:
|
|
28
28
|
- Rakefile
|
29
29
|
- collection.gemspec
|
30
30
|
- lib/array_collection.rb
|
31
|
+
- lib/array_collection/array_components/data_handling.rb
|
32
|
+
- lib/array_collection/array_components/filtering.rb
|
33
|
+
- lib/array_collection/array_components/joining.rb
|
34
|
+
- lib/array_collection/array_components/key_filtering.rb
|
35
|
+
- lib/array_collection/array_components/mapping.rb
|
31
36
|
- lib/array_collection/collect.rb
|
32
37
|
- lib/array_collection/collection_array.rb
|
33
38
|
- lib/array_collection/collection_filter.rb
|
34
39
|
- lib/array_collection/data_accessor.rb
|
35
40
|
- lib/array_collection/helper.rb
|
36
41
|
- lib/array_collection/hooks.rb
|
42
|
+
- lib/array_collection/json_parser.rb
|
37
43
|
- lib/array_collection/version.rb
|
38
44
|
- package.json
|
39
45
|
- sig/collection.rbs
|