filter 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/filter.rb CHANGED
@@ -1,3 +1,7 @@
1
+ require "filter/condition"
2
+ require "filter/or"
3
+ require "filter/and"
4
+
1
5
  # == Synopsys
2
6
  # Extension for Ruby <code>Enumerable</code> module
3
7
  #
@@ -33,47 +37,12 @@ module Enumerable
33
37
 
34
38
  # move +block+ to +patterns+ if no +patterns+ given
35
39
  patterns, block = [block], nil if block_given? && patterns.empty?
36
- conditions = patterns.map { |pattern| filter_condition(pattern) }
37
-
38
40
  # match elements against all patterns using +OR+ operator
39
- filtered = select do |obj|
40
- conditions.any? { |condition| condition.call(obj) }
41
- end
41
+ conditions = Filter.or(*patterns)
42
+
43
+ filtered = select { |obj| conditions === obj }
42
44
 
43
45
  # also transform elements if block given
44
46
  block ? filtered.map(&block) : filtered
45
47
  end
46
-
47
- private
48
- def filter_condition(pattern) #:nodoc:
49
- # create filter condition from pattern
50
- case pattern
51
- when NilClass then proc { true }
52
-
53
- when Class, Module then
54
- proc do |e|
55
- e.is_a?(Class) || e.is_a?(Module) ?
56
- e <= pattern :
57
- e.is_a?(pattern)
58
- end
59
-
60
- when Symbol, Proc, Method then pattern.to_proc
61
-
62
- when Array then # enum.filter [:even?, :positive?, :cool?, proc { |n| n < 10 }]
63
- proc do |e|
64
- pattern.all? { |condition| filter_condition(condition).call(e) }
65
- end
66
-
67
- when Hash then # enum.filter :to_i => :even?, :ceil => :odd?
68
- proc do |e|
69
- pattern.all? do |attribute, condition|
70
- filter_condition(condition).call(attribute.to_proc.call(e))
71
- end
72
- end
73
-
74
- when TrueClass, FalseClass then proc { |e| !!e == pattern }
75
-
76
- else proc { |e| pattern === e } # otherwise - String, Regexp, Numeric etc.
77
- end
78
- end
79
48
  end
data/lib/filter/and.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "filter/condition"
2
+
3
+ module Filter
4
+ class And < Condition
5
+ def initialize(*patterns)
6
+ @matchers = patterns.map { |pattern| Matcher.new(pattern) }
7
+ end
8
+
9
+ def ===(other)
10
+ @matchers.all? { |m| m === other }
11
+ end
12
+ end
13
+
14
+ def and(*patterns)
15
+ And.new(*patterns)
16
+ end
17
+ module_function :and
18
+ end
@@ -0,0 +1,23 @@
1
+ require "filter/matcher"
2
+
3
+ module Filter
4
+ class Condition
5
+ def initialize(pattern)
6
+ @matcher = Filter::Matcher.new(pattern)
7
+ end
8
+
9
+ def ===(another)
10
+ @matcher === another
11
+ end
12
+
13
+ def and(other)
14
+ Filter.and(self, other)
15
+ end
16
+ alias & and
17
+
18
+ def or(other)
19
+ Filter.or(self, other)
20
+ end
21
+ alias | or
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ require "filter/matchers/base"
2
+ require "filter/matchers/array"
3
+ require "filter/matchers/boolean"
4
+ require "filter/matchers/class"
5
+ require "filter/matchers/hash"
6
+ require "filter/matchers/nil"
7
+ require "filter/matchers/symbol"
8
+
9
+ module Filter
10
+ module Matcher
11
+ MAPPING = {
12
+ [NilClass] => Filter::Matchers::Nil,
13
+ [TrueClass, FalseClass] => Filter::Matchers::Boolean,
14
+ [Class, Module] => Filter::Matchers::Class,
15
+ [Array] => Filter::Matchers::Array,
16
+ [Symbol, Proc, Method, UnboundMethod] => Filter::Matchers::Symbol,
17
+ [Hash] => Filter::Matchers::Hash,
18
+ }
19
+
20
+ def new(pattern)
21
+ klass = nil
22
+
23
+ MAPPING.each_pair do |classes, matcher_klass|
24
+ klass = matcher_klass if classes.any? { |cls| pattern.is_a?(cls) }
25
+ end
26
+
27
+ klass = Filter::Matchers::Base if klass.nil?
28
+
29
+ klass.new(pattern)
30
+ end
31
+ module_function :new
32
+ end
33
+
34
+ def match(pattern)
35
+ Matcher.new(pattern)
36
+ end
37
+ module_function :match
38
+ end
@@ -0,0 +1,13 @@
1
+ module Filter
2
+ module Matchers
3
+ class Array < Base
4
+ def initialize(pattern)
5
+ @pattern = pattern.map(&:to_proc)
6
+ end
7
+
8
+ def ===(other)
9
+ pattern.all? { |p| p === other }
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,25 @@
1
+ module Filter
2
+ module Matchers
3
+ class Base
4
+ attr_reader :pattern
5
+
6
+ def initialize(pattern)
7
+ @pattern = pattern
8
+ end
9
+
10
+ def ===(other)
11
+ pattern === other
12
+ end
13
+
14
+ def and(other)
15
+ Filter.and(self, other)
16
+ end
17
+ alias & and
18
+
19
+ def or(other)
20
+ Filter.or(self, other)
21
+ end
22
+ alias | or
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ module Filter
2
+ module Matchers
3
+ class Boolean < Base
4
+ def ===(other)
5
+ !!other == pattern
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Filter
2
+ module Matchers
3
+ class Class < Base
4
+ def ===(other)
5
+ other.is_a?(::Class) || other.is_a?(::Module) ?
6
+ other <= pattern :
7
+ other.is_a?(pattern)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Filter
2
+ module Matchers
3
+ class Hash < Base
4
+ def initialize(pattern)
5
+ @pattern = ::Hash[pattern.map { |k, v| [k.to_proc, Filter::Matcher.new(v)]}]
6
+ end
7
+
8
+ def ===(other)
9
+ pattern.all? do |attr, pattern|
10
+ pattern === attr.call(other)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module Filter
2
+ module Matchers
3
+ class Nil < Base
4
+ # nil condition always results to true
5
+ def ===(other)
6
+ true
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ module Filter
2
+ module Matchers
3
+ class Symbol < Base
4
+ def initialize(pattern)
5
+ @pattern = pattern.to_proc
6
+ end
7
+
8
+ def ===(other)
9
+ pattern.call(other)
10
+ end
11
+ end
12
+ end
13
+ end
data/lib/filter/or.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "filter/condition"
2
+
3
+ module Filter
4
+ class Or < Condition
5
+ def initialize(*patterns)
6
+ @matchers = patterns.map { |pattern| Matcher.new(pattern) }
7
+ end
8
+
9
+ def ===(other)
10
+ @matchers.any? { |m| m === other }
11
+ end
12
+ end
13
+
14
+ def or(*patterns)
15
+ Or.new(*patterns)
16
+ end
17
+ module_function :or
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Filter
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/spec/filter_spec.rb CHANGED
@@ -57,4 +57,14 @@ describe Enumerable do
57
57
  it "should match using OR operator" do
58
58
  [0, 2, 3, 4].filter(:zero?, :odd?).should == [0, 3]
59
59
  end
60
+
61
+ it "should be flexible" do
62
+ conditions = Filter.match(:even?) | :odd? | :zero?
63
+
64
+ [0, 1, 2].filter(conditions).should == [0, 1, 2]
65
+
66
+ # 0 and negative
67
+ conditions = Filter.and(:zero?, :even?) | proc { |n| n < 0 }
68
+ [-1, 0, 1].filter(conditions).should == [-1, 0]
69
+ end
60
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &20615240 !ruby/object:Gem::Requirement
16
+ requirement: &13830380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *20615240
24
+ version_requirements: *13830380
25
25
  description: ! "== Synopsys\n<code>Enumerable#filter</code> - extended <code>Enumerable#select</code>\n\n==
26
26
  Examples\nString filter (acts like <code>Enumerable#grep</code>):\n [1, 2, 3, 'ab'].filter(/a/)
27
27
  \ # => ['ab']\n [1, 2, 3, '3'].filter('3') # => ['3']\n\nYou
@@ -50,6 +50,17 @@ files:
50
50
  - Rakefile
51
51
  - filter.gemspec
52
52
  - lib/filter.rb
53
+ - lib/filter/and.rb
54
+ - lib/filter/condition.rb
55
+ - lib/filter/matcher.rb
56
+ - lib/filter/matchers/array.rb
57
+ - lib/filter/matchers/base.rb
58
+ - lib/filter/matchers/boolean.rb
59
+ - lib/filter/matchers/class.rb
60
+ - lib/filter/matchers/hash.rb
61
+ - lib/filter/matchers/nil.rb
62
+ - lib/filter/matchers/symbol.rb
63
+ - lib/filter/or.rb
53
64
  - lib/filter/version.rb
54
65
  - spec/filter_spec.rb
55
66
  - spec/test_helper.rb