jrf 0.1.10 → 0.1.12

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: 1a42d35a082e26fb5ebc35733d705169793e42491eb20040aff884f65e016cf7
4
- data.tar.gz: 909ac3ea12a5bf4bf805ea65d25f03e01843efcc944a0180cda90d8d8dd89b8f
3
+ metadata.gz: ddf9bb5a12260eea615d0107dc7374dec2b5a3fe81c51791ea7e7ffea359d12f
4
+ data.tar.gz: d556b7d230185a9c397af45abaa08b912f485f3a1494bebdf86f2ef44be81c64
5
5
  SHA512:
6
- metadata.gz: e38ba5d6ec1ae98cefe2d9ce848d3702ba2bddb6f2858df0b9055da84c08dd3371a1b3d6290ae74796b858765c5af5cbc4c68180fde6b161b78cbbefdfdbc84d
7
- data.tar.gz: cd5e4a2f2d93b34a45c3121e021b9ca23974476b82e3169f17ed6bce44600ecc82bcb5dc35cf3fc52cafb5749dd8be21370f7e5f2c33031774619f416e3c3518
6
+ metadata.gz: e7642e5e7c50e9b4da7f28bf906bf432ee7c6d377839af2ff2b73d299c044e08566876bd3d33d5492abe9432b58f0871df2ebb9d4e7ec45ffe02a495fad1e2fc
7
+ data.tar.gz: '0629e81b1c9cf8070fb0a1fcbe409cf026bb62f72da9855d32fe9f253552de51a21f663b616abdc3b474dd705d9067512838fe5f0e33293f423636a5ea18167f'
@@ -59,6 +59,10 @@ module Jrf
59
59
  end
60
60
  end
61
61
 
62
+ define_reducer(:count_if) do |_ctx, condition, block: nil|
63
+ { value: condition, initial: 0, step: ->(acc, v) { v ? (acc + 1) : acc } }
64
+ end
65
+
62
66
  define_reducer(:min) do |_ctx, value, block: nil|
63
67
  { value: value, initial: nil, step: ->(acc, v) { v.nil? ? acc : (acc.nil? || v < acc ? v : acc) } }
64
68
  end
@@ -170,16 +174,22 @@ module Jrf
170
174
  @__jrf_current_stage.step_reduce(current_input, initial: initial, &block)
171
175
  end
172
176
 
173
- def map(&block)
177
+ def map(collection = nil, &block)
174
178
  raise ArgumentError, "map requires a block" unless block
175
179
 
176
- @__jrf_current_stage.step_map(:map, @obj, &block)
180
+ @__jrf_current_stage.step_map(:map, collection || current_input, &block)
177
181
  end
178
182
 
179
- def map_values(&block)
183
+ def map_values(collection = nil, &block)
180
184
  raise ArgumentError, "map_values requires a block" unless block
181
185
 
182
- @__jrf_current_stage.step_map(:map_values, @obj, &block)
186
+ @__jrf_current_stage.step_map(:map_values, collection || current_input, &block)
187
+ end
188
+
189
+ def apply(collection = nil, &block)
190
+ raise ArgumentError, "apply requires a block" unless block
191
+
192
+ @__jrf_current_stage.step_apply(collection || current_input, &block)
183
193
  end
184
194
 
185
195
  def group_by(key, &block)
data/lib/jrf/stage.rb CHANGED
@@ -113,6 +113,35 @@ module Jrf
113
113
  ReducerToken.new(idx)
114
114
  end
115
115
 
116
+ def step_apply(collection, &block)
117
+ raise TypeError, "apply expects Array, got #{collection.class}" unless collection.is_a?(Array)
118
+
119
+ apply_reducers = []
120
+ template = nil
121
+ results = []
122
+
123
+ collection.each do |v|
124
+ with_scoped_reducers(apply_reducers) do
125
+ result = @ctx.send(:__jrf_with_current_input, v) { block.call(v) }
126
+ template ||= result
127
+ results << result
128
+ end
129
+ end
130
+
131
+ if apply_reducers.any?
132
+ self.class.resolve_template(template, apply_reducers)
133
+ else
134
+ results.each_with_object([]) do |mapped, arr|
135
+ next if mapped.equal?(Control::DROPPED)
136
+ if mapped.is_a?(Control::Flat)
137
+ arr.concat(Array(mapped.value))
138
+ else
139
+ arr << mapped
140
+ end
141
+ end
142
+ end
143
+ end
144
+
116
145
  def step_group_by(key, &block)
117
146
  idx = @cursor
118
147
  map_reducer = (@reducers[idx] ||= MapReducer.new(:group_by, false))
data/lib/jrf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Jrf
4
- VERSION = "0.1.10"
4
+ VERSION = "0.1.12"
5
5
  end
data/test/jrf_test.rb CHANGED
@@ -534,6 +534,23 @@ stdout, stderr, status = run_jrf('count(_["foo"])', input_with_nil)
534
534
  assert_success(status, stderr, "count(expr) ignores nil")
535
535
  assert_equal(%w[2], lines(stdout), "count(expr) ignores nil output")
536
536
 
537
+ # count_if
538
+ input_count_if = <<~NDJSON
539
+ {"x":1}
540
+ {"x":-2}
541
+ {"x":3}
542
+ {"x":-4}
543
+ {"x":5}
544
+ NDJSON
545
+
546
+ stdout, stderr, status = run_jrf('count_if(_["x"] > 0)', input_count_if)
547
+ assert_success(status, stderr, "count_if")
548
+ assert_equal(%w[3], lines(stdout), "count_if output")
549
+
550
+ stdout, stderr, status = run_jrf('[count_if(_["x"] > 0), count_if(_["x"] < 0)]', input_count_if)
551
+ assert_success(status, stderr, "count_if multiple")
552
+ assert_equal(["[3,2]"], lines(stdout), "count_if multiple output")
553
+
537
554
  input_all_nil = <<~NDJSON
538
555
  {"foo":null}
539
556
  {"bar":1}
@@ -847,6 +864,44 @@ stdout, stderr, status = run_jrf('_["values"] >> map { |x| x + 1 } >> map { |x|
847
864
  assert_success(status, stderr, "chained map transforms")
848
865
  assert_equal(['[20,110,1010]', '[30,210,2010]', '[40,310,3010]'], lines(stdout), "chained map transforms output")
849
866
 
867
+ stdout, stderr, status = run_jrf('map { map { |y| [ sum(y[0]), sum(y[1]) ] } }', "[[[1,2]]]\n[[[3,4]]]\n")
868
+ assert_success(status, stderr, "nested map reducer binds to current target")
869
+ assert_equal(['[[[4,6]]]'], lines(stdout), "nested map reducer output")
870
+
871
+ stdout, stderr, status = run_jrf('map_values { |obj| map_values { |v| sum(v) } }', "{\"a\":{\"x\":1,\"y\":2},\"b\":{\"x\":10,\"y\":20}}\n{\"a\":{\"x\":3,\"y\":4},\"b\":{\"x\":30,\"y\":40}}\n")
872
+ assert_success(status, stderr, "nested map_values reducer binds to current target")
873
+ assert_equal(['{"a":{"x":4,"y":6},"b":{"x":40,"y":60}}'], lines(stdout), "nested map_values reducer output")
874
+
875
+ # apply - aggregation
876
+ stdout, stderr, status = run_jrf('[apply { |x| sum(x["foo"]) }, _.length]', '[{"foo":1},{"foo":2}]' + "\n" + '[{"foo":10}]' + "\n")
877
+ assert_success(status, stderr, "apply with sum")
878
+ assert_equal(["[3,2]", "[10,1]"], lines(stdout), "apply with sum output")
879
+
880
+ # apply - passthrough
881
+ stdout, stderr, status = run_jrf('apply { |x| x["foo"] }', '[{"foo":1},{"foo":2}]' + "\n")
882
+ assert_success(status, stderr, "apply passthrough")
883
+ assert_equal(["[1,2]"], lines(stdout), "apply passthrough output")
884
+
885
+ # apply - percentile
886
+ stdout, stderr, status = run_jrf('apply { |x| percentile(x, 0.5) }', '[10,20,30]' + "\n")
887
+ assert_success(status, stderr, "apply with percentile")
888
+ assert_equal(["20"], lines(stdout), "apply with percentile output")
889
+
890
+ # apply with explicit collection inside map
891
+ stdout, stderr, status = run_jrf('map { |o| [apply(o["vals"]) { |x| sum(x) }, o["name"]] }', '[{"name":"a","vals":[1,2]},{"name":"b","vals":[10,20]}]' + "\n")
892
+ assert_success(status, stderr, "apply with explicit collection")
893
+ assert_equal(['[[3,"a"],[30,"b"]]'], lines(stdout), "apply with explicit collection output")
894
+
895
+ # map with explicit collection
896
+ stdout, stderr, status = run_jrf('map(_["items"]) { |x| x * 2 }', '{"items":[1,2,3]}' + "\n")
897
+ assert_success(status, stderr, "map with explicit collection")
898
+ assert_equal(["[2,4,6]"], lines(stdout), "map with explicit collection output")
899
+
900
+ # map_values with explicit collection
901
+ stdout, stderr, status = run_jrf('map_values(_["data"]) { |v| v * 10 }', '{"data":{"a":1,"b":2}}' + "\n")
902
+ assert_success(status, stderr, "map_values with explicit collection")
903
+ assert_equal(['{"a":10,"b":20}'], lines(stdout), "map_values with explicit collection output")
904
+
850
905
  input_gb = <<~NDJSON
851
906
  {"status":200,"path":"/a","latency":10}
852
907
  {"status":404,"path":"/b","latency":50}
@@ -944,10 +999,18 @@ assert_equal([[2, 3], [4, 5]], j.call([[1, 2], [3, 4]]), "library map transform"
944
999
  j = Jrf.new(proc { map { |x| sum(x) } })
945
1000
  assert_equal([[4, 6]], j.call([[1, 2], [3, 4]]), "library map reduce")
946
1001
 
1002
+ # nested map reduce binds to current target
1003
+ j = Jrf.new(proc { map { map { |y| [sum(y[0]), sum(y[1])] } } })
1004
+ assert_equal([[[[4, 6]]]], j.call([[[[1, 2]]], [[[3, 4]]]]), "library nested map reduce")
1005
+
947
1006
  # map_values transform
948
1007
  j = Jrf.new(proc { map_values { |v| v * 10 } })
949
1008
  assert_equal([{"a" => 10, "b" => 20}], j.call([{"a" => 1, "b" => 2}]), "library map_values transform")
950
1009
 
1010
+ # nested map_values reduce binds to current target
1011
+ j = Jrf.new(proc { map_values { |obj| map_values { |v| sum(v) } } })
1012
+ assert_equal([{"a" => {"x" => 4, "y" => 6}, "b" => {"x" => 40, "y" => 60}}], j.call([{"a" => {"x" => 1, "y" => 2}, "b" => {"x" => 10, "y" => 20}}, {"a" => {"x" => 3, "y" => 4}, "b" => {"x" => 30, "y" => 40}}]), "library nested map_values reduce")
1013
+
951
1014
  # map hash transform
952
1015
  j = Jrf.new(proc { map { |k, v| "#{k}=#{v}" } })
953
1016
  assert_equal([["a=1", "b=2"]], j.call([{"a" => 1, "b" => 2}]), "library map hash transform")
@@ -960,6 +1023,30 @@ assert_equal([[["a", 1], ["b", 2]]], j.call([{"a" => 1, "b" => 2}]), "library ma
960
1023
  j = Jrf.new(proc { map { |k, v| sum(v + k.length) } })
961
1024
  assert_equal([[5, 7]], j.call([{"a" => 1, "b" => 2}, {"a" => 2, "b" => 3}]), "library map hash reduce")
962
1025
 
1026
+ # apply - aggregation
1027
+ j = Jrf.new(proc { [apply { |x| sum(x["foo"]) }, _.length] })
1028
+ assert_equal([[3, 2], [10, 1]], j.call([[{"foo" => 1}, {"foo" => 2}], [{"foo" => 10}]]), "library apply reducer")
1029
+
1030
+ # apply - passthrough
1031
+ j = Jrf.new(proc { apply { |x| x["foo"] } })
1032
+ assert_equal([[1, 2]], j.call([[{"foo" => 1}, {"foo" => 2}]]), "library apply passthrough")
1033
+
1034
+ # apply - percentile
1035
+ j = Jrf.new(proc { apply { |x| percentile(x, 0.5) } })
1036
+ assert_equal([20], j.call([[10, 20, 30]]), "library apply percentile")
1037
+
1038
+ # apply with explicit collection inside map
1039
+ j = Jrf.new(proc { map { |o| [apply(o["vals"]) { |x| sum(x) }, o["name"]] } })
1040
+ assert_equal([[[3, "a"], [30, "b"]]], j.call([[{"name" => "a", "vals" => [1, 2]}, {"name" => "b", "vals" => [10, 20]}]]), "library apply explicit collection")
1041
+
1042
+ # map with explicit collection
1043
+ j = Jrf.new(proc { map(_["items"]) { |x| x * 2 } })
1044
+ assert_equal([[2, 4, 6]], j.call([{"items" => [1, 2, 3]}]), "library map explicit collection")
1045
+
1046
+ # map_values with explicit collection
1047
+ j = Jrf.new(proc { map_values(_["data"]) { |v| v * 10 } })
1048
+ assert_equal([{"a" => 10, "b" => 20}], j.call([{"data" => {"a" => 1, "b" => 2}}]), "library map_values explicit collection")
1049
+
963
1050
  # group_by
964
1051
  j = Jrf.new(proc { group_by(_["k"]) { count() } })
965
1052
  assert_equal([{"x" => 2, "y" => 1}], j.call([{"k" => "x"}, {"k" => "x"}, {"k" => "y"}]), "library group_by")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jrf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.10
4
+ version: 0.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - kazuho