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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99c99035901ba4bb263bd3ed0127a9359fd4480d539c64b41376d458e9dd7331
4
- data.tar.gz: 2b1ebc21ac78ebd94d53f75dcb9ce79b884cb5cac89d9b4bdb9645a3c5989b02
3
+ metadata.gz: ef33c3e653a6e11b9d4c92b2524b71f772cdb1e49399ab6d9da1138af9d08612
4
+ data.tar.gz: 4c029f0f9e11c739b26737bb7db34573221c377e76958b872a3813f87dab7810
5
5
  SHA512:
6
- metadata.gz: 1a9712fb542f0f87bb99fed58eca9091ad4e91195ba9b4f59ec55dbd6d2c799e71464d8b48d35c5fe9dec88a0eeff9efec843d6f333279d5e8f534619978e959
7
- data.tar.gz: 8f0ca49396f74b030ebf7ba9261d93d077e07f7d456eb6a0876ec653feed78a8939e0dacd1104b832921eef758228b8d86c1315764a8ff57ebc04669ca727c54
6
+ metadata.gz: d6b3624550f8f9e00ddffcf950b198fe4f7bfc4c544ae258d9d4c2da1eac0a3ecfe4f09b05cbeff050b047d25d9ab2449926473417ceb63bd4a79aa762ac0d6f
7
+ data.tar.gz: 89011dea94eb965e5cdcadb013b92a388b5f3ed5a3fcd459c2bfc28a24a5cfef3c1af34099d92b3fca20511b379e99789bb4ea40e2afd59a3baea6b556fac1d9
data/.rubocop.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  require:
2
2
  - rubocop-rspec
3
3
  - rubocop-rake
4
+ - rubocop-performance
4
5
 
5
6
  AllCops:
6
7
  TargetRubyVersion: 3.0
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.2.8](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.14...v0.2.8) (2024-03-26)
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
- * **changelog:** bump changlog ([b50d44a](https://github.com/WailanTirajoh/ruby_collection/commit/b50d44ad655287ecbe0b934341d0a031f12e7cac))
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
- ## [0.2.13](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.12...v0.2.13) (2024-03-26)
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
- ## [0.2.11](https://github.com/WailanTirajoh/ruby_collection/compare/v0.2.10...v0.2.11) (2024-03-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
- * **gem:** remove required mfa ([7b4b9c4](https://github.com/WailanTirajoh/ruby_collection/commit/7b4b9c432002ff4381da0004d3ad4d6912b8b2d8))
36
- * **gem:** remove required mfa ([d342636](https://github.com/WailanTirajoh/ruby_collection/commit/d3426369e6f1dff96abc568689fc9ec4381967f1))
37
- * **lint:** Lintfix ([be99af7](https://github.com/WailanTirajoh/ruby_collection/commit/be99af72b9f3a2cfadad224aff191aafb48a6d45))
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
- * **collect:** add left_join, right_join, full_join ([bca2af5](https://github.com/WailanTirajoh/ruby_collection/commit/bca2af5ec5e9b078fb7c75155ae0e1f79e8e1732))
42
- * **collection:** add sort, append, prepend, map and test chainable collection ([8084fc9](https://github.com/WailanTirajoh/ruby_collection/commit/8084fc966b2a3540c3e5f8935b56d795d8bf8b69))
43
- * **collection:** first initial collection & array fn ([2009281](https://github.com/WailanTirajoh/ruby_collection/commit/2009281a2d53d8ffa4a0090fd4e363329ac0f4ed))
44
- * **collection:** first initial collection & array fn ([04efd77](https://github.com/WailanTirajoh/ruby_collection/commit/04efd77f32bae72e1ad53391744bbfde12123754))
45
- * **data:** data accessor based on dot notation ([92efb9e](https://github.com/WailanTirajoh/ruby_collection/commit/92efb9e48f6dbeeb72c3f2bc1090bd4cd9f903c2))
46
- * **diff:** add diff & refactor array spec ([d0e3a66](https://github.com/WailanTirajoh/ruby_collection/commit/d0e3a66c8bd2d6d4f7ba706537b01e18929a3d51))
47
- * **helper:** add collect helper ([13c4efb](https://github.com/WailanTirajoh/ruby_collection/commit/13c4efbbc481960227f361208818471a197df752))
48
- * **join:** inner join ([d1f011b](https://github.com/WailanTirajoh/ruby_collection/commit/d1f011b76560ad26fdecdef1c01cdc7291cbac6e))
49
- * **utils:** add when, only, except ([77da9e8](https://github.com/WailanTirajoh/ruby_collection/commit/77da9e848ae60b771f24cf623b73df85f80b1eea))
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
- @items = get_arrayable_items(items)
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 filter(&block)
20
- self.class.new(ArrayCollection::CollectionArray.filter(@items, &block))
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 sort(&block)
40
- self.class.new(@items.sort(&block))
41
- end
33
+ def when(boolean)
34
+ return self if boolean == false
42
35
 
43
- def sort_desc(&block)
44
- self.class.new(@items.sort(&block).reverse)
36
+ yield(self)
45
37
  end
46
38
 
47
- def sort_by_key(key)
48
- self.class.new(@items.sort_by { |item| item[key] })
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
- self.class.new(ArrayCollection::CollectionArray.append(@items, value))
46
+ clone(ArrayCollection::CollectionArray.append(@items, value))
53
47
  end
54
48
 
55
49
  def prepend(value)
56
- self.class.new(ArrayCollection::CollectionArray.prepend(@items, value))
50
+ clone(ArrayCollection::CollectionArray.prepend(@items, value))
57
51
  end
58
52
 
59
- def map(&block)
60
- self.class.new(ArrayCollection::CollectionArray.map(@items, &block))
53
+ def diff(items)
54
+ clone(ArrayCollection::CollectionArray.diff(@items, items))
61
55
  end
62
56
 
63
- def when(boolean)
64
- return self if boolean == false
57
+ def filter(&block)
58
+ clone(ArrayCollection::CollectionArray.filter(@items, &block))
59
+ end
65
60
 
66
- yield(self)
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
- self.class.new(ArrayCollection::CollectionArray.only(@items, *keys))
74
+ clone(ArrayCollection::CollectionArray.only(@items, *keys.map(&:to_sym)))
71
75
  end
72
76
 
73
77
  def except(*keys)
74
- self.class.new(ArrayCollection::CollectionArray.except(@items, *keys))
78
+ clone(ArrayCollection::CollectionArray.except(@items, *keys.map(&:to_sym)))
75
79
  end
76
80
 
77
- def diff(items)
78
- self.class.new(ArrayCollection::CollectionArray.diff(@items, items))
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
- self.class.new(ArrayCollection::CollectionArray.inner_join(@items, get_arrayable_items(items), left_key,
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
- self.class.new(ArrayCollection::CollectionArray.left_join(@items, get_arrayable_items(items), left_key,
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
- self.class.new(ArrayCollection::CollectionArray.right_join(@items, get_arrayable_items(items), left_key,
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
- self.class.new(ArrayCollection::CollectionArray.full_join(@items, get_arrayable_items(items), left_key,
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? { |item| item.is_a?(Hash) }
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 "collection_filter"
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
- def filter(array, &block)
10
- array.select(&block)
11
- end
12
-
13
- def where(array, *args)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ArrayCollection
4
- VERSION = "0.2.8"
4
+ VERSION = "0.3.1"
5
5
  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.2.8
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-26 00:00:00.000000000 Z
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