filter 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,26 @@
1
1
  == Synopsys
2
- Enumerable#filter - extended Enumerable#select
2
+ <code>Enumerable#filter</code> - extended <code>Enumerable#select</code>
3
3
 
4
4
  == Examples
5
- String filter (acts like Enumerable#grep):
5
+ String filter (acts like <code>Enumerable#grep</code>):
6
6
  [1, 2, 3, 'ab'].filter(/a/) # => ['ab']
7
7
  [1, 2, 3, '3'].filter('3') # => ['3']
8
8
 
9
- You can pass a <tt>Proc</tt> or <tt>Symbol</tt>. Methods and blocks are allowed too:
9
+ You can pass a <code>Proc</code> or <code>Symbol</code>. Methods and blocks are allowed too:
10
10
  [1, 2, 3].filter(&:even?) # => [2]
11
11
  [1, 2, 3].filter(:even?) # => [2]
12
12
  [1, 2, 4].filter { |num| num.even? } # => [2, 4]
13
13
 
14
- <tt>Enumerable#filter</tt> can match against enumerable items attributes. Like this:
14
+ <code>Enumerable#filter</code> can match against enumerable items attributes. Like this:
15
15
  [1, 2, 3, 4.2].filter :to_i => :even? # => [2, 4]
16
16
 
17
- If the block is supplied, each matching element is passed to it, and the blocks result is stored in the output enumerator.
17
+ If the block is supplied, each matching element is passed to it, and the block's result is stored in the output array.
18
18
  [1, 2, 4].filter(&:even?) { |n| n + 1 } # => [3, 5]
19
19
 
20
- <tt>Enumerable#filter</tt> also accepts <tt>true</tt> or <tt>false</tt> as argument:
20
+ <code>Enumerable#filter</code> also accepts <code>true</code> or <code>false</code> as argument:
21
21
  [0, false, 2, nil].filter(true) # => [0, 2]
22
22
  [0, false, 2, nil].filter(false) # => [false, nil]
23
+
24
+ <code>Enumerable#filter</code> also supports <code>OR</code> operator!
25
+ Just pass many patterns, they will be joined together with <code>OR</code> operator.
26
+ [0, 2, 3, 4].filter(:zero?, :odd?) # => [0, 3]
@@ -1,8 +1,8 @@
1
- # == Synpsys
2
- # Extension for Ruby Enumerable module
1
+ # == Synopsys
2
+ # Extension for Ruby <code>Enumerable</code> module
3
3
  #
4
4
  # == Description
5
- # Extends Enumerable module with +filter+ method - enhanced version of Enumerable#select
5
+ # Extends <code>Enumerable</code> module with <code>filter</code> method - enhanced version of <code>Enumerable#select</code>.
6
6
  #
7
7
  # == Examples
8
8
  # [1, 2, 3, 'ab'].filter(/a/) # => ['ab']
@@ -11,50 +11,69 @@
11
11
  # [1, 2, 4].filter { |num| num.even? } # => [2, 4]
12
12
  # [1, 2, 4].filter(:even?) { |n| n + 1 } # => [3, 5]
13
13
  # [0, false, 2, nil].filter(true) # => [0, 2]
14
+ #
15
+ # <code>Enumerable#filter</code> also supports <code>OR</code> operator! Just pass many patterns as arguments.
16
+ # This snippet will match elements responding to <code>zero?</code> or <code>odd?</code> methods with <code>true</code>.
17
+ # [0, 2, 3, 4].filter(:zero?, :odd?) # => [0, 3]
14
18
  module Enumerable
15
19
  # Extended Enumerable#select combibed with Enumerable#collect
16
20
  #
17
- # When String or Regexp passed it acts as built-in +grep+ method, but return Enumerator instead of Array
18
- # Also you can pass Symbol, Proc or block
21
+ # When String or Regexp passed it acts as built-in <code>Enumerable#grep</code> method
22
+ # Also you can pass <code>Symbol, Proc, Method, Array, Hash, Class, Module, true, false, nil</code>.
23
+ # If the <code>block</code> is supplied without other arguments it will be used as filter.
24
+ # If the <code>block</code> is supplied with <code>patterns</code>,
25
+ # each matching element is passed to it, and the block's result is stored in the output array.
19
26
  #
20
- # @param pattern [Numeric|String|Regexp|Symbol|Proc|Method|NilClass|Hash|TrueClass|FalseClass|Module|Class]
27
+ # @param patterns *[Numeric|String|Regexp|Symbol|Proc|Method|NilClass|Hash|TrueClass|FalseClass|Module|Class]
21
28
  # @param block [Proc]
22
- def filter(pattern = nil, &block) # :yields: obj
23
- pattern, block = block, nil if block_given? && pattern.nil?
29
+ # @return [Enumerable]
30
+ def filter(*patterns, &block) # :yields: obj
31
+ # do nothing on null input
32
+ return self if !block_given? && patterns.empty?
33
+
34
+ # move +block+ to +patterns+ if no +patterns+ given
35
+ patterns, block = [block], nil if block_given? && patterns.empty?
36
+ conditions = patterns.map { |pattern| filter_condition(pattern) }
37
+
38
+ # match elements against all patterns using +OR+ operator
39
+ filtered = select do |obj|
40
+ conditions.any? { |condition| condition.call(obj) }
41
+ end
24
42
 
25
- filtered = case pattern
26
- when NilClass then self
43
+ # also transform elements if block given
44
+ block ? filtered.map(&block) : filtered
45
+ 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 }
27
52
 
28
53
  when Class, Module then
29
- select do |e|
54
+ proc do |e|
30
55
  e.is_a?(Class) || e.is_a?(Module) ?
31
56
  e <= pattern :
32
57
  e.is_a?(pattern)
33
58
  end
34
59
 
35
- when Symbol, Proc, Method then select(&pattern.to_proc)
60
+ when Symbol, Proc, Method then pattern.to_proc
36
61
 
37
62
  when Array then # enum.filter [:even?, :positive?, :cool?, proc { |n| n < 10 }]
38
- pattern.reduce(self) do |chain, local_pattern|
39
- chain.select(&local_pattern.to_proc)
63
+ proc do |e|
64
+ pattern.all? { |condition| filter_condition(condition).call(e) }
40
65
  end
41
66
 
42
67
  when Hash then # enum.filter :to_i => :even?, :ceil => :odd?
43
- pattern.reduce(self) do |chain, pair|
44
- attr, local_pattern = pair.map(&:to_proc)
45
-
46
- chain.select do |element|
47
- local_pattern.call(attr.call(element))
68
+ proc do |e|
69
+ pattern.all? do |attribute, condition|
70
+ filter_condition(condition).call(attribute.to_proc.call(e))
48
71
  end
49
72
  end
50
73
 
51
- when TrueClass, FalseClass then select { |e| !!e == pattern }
74
+ when TrueClass, FalseClass then proc { |e| !!e == pattern }
52
75
 
53
- else select { |e| pattern === e } # otherwise - String, Regexp, Numeric etc.
76
+ else proc { |e| pattern === e } # otherwise - String, Regexp, Numeric etc.
54
77
  end
55
-
56
- # also transform elements if block given
57
- block ? filtered.map(&block) : filtered
58
78
  end
59
-
60
- end
79
+ end
@@ -1,3 +1,3 @@
1
1
  module Filter
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -53,4 +53,8 @@ describe Enumerable do
53
53
  [0, false, 2, nil].filter(true).should == [0, 2]
54
54
  [0, false, 2, nil].filter(false).should == [false, nil]
55
55
  end
56
+
57
+ it "should match using OR operator" do
58
+ [0, 2, 3, 4].filter(:zero?, :odd?).should == [0, 3]
59
+ end
56
60
  end
metadata CHANGED
@@ -1,52 +1,48 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: filter
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 3
9
- version: 0.0.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Alexey Mikhaylov
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-12-12 00:00:00 +06:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-12 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rspec
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &20615240 !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
31
22
  type: :development
32
- version_requirements: *id001
33
- description: "== Synopsys\n\
34
- Enumerable#filter - extended Enumerable#select\n\n\
35
- == Examples\n\
36
- String filter (acts like Enumerable#grep):\n [1, 2, 3, 'ab'].filter(/a/) # => ['ab']\n [1, 2, 3, '3'].filter('3') # => ['3']\n\n\
37
- You can pass a <tt>Proc</tt> or <tt>Symbol</tt>. Methods and blocks are allowed too:\n [1, 2, 3].filter(&:even?) # => [2]\n [1, 2, 3].filter(:even?) # => [2]\n [1, 2, 4].filter { |num| num.even? } # => [2, 4]\n\n\
38
- <tt>Enumerable#filter</tt> can match against enumerable items attributes. Like this:\n [1, 2, 3, 4.2].filter :to_i => :even? # => [2, 4]\n\n\
39
- If the block is supplied, each matching element is passed to it, and the block\xE2\x80\x99s result is stored in the output enumerator.\n [1, 2, 4].filter(&:even?) { |n| n + 1 } # => [3, 5]\n\n\
40
- <tt>Enumerable#filter</tt> also accepts <tt>true</tt> or <tt>false</tt> as argument:\n [0, false, 2, nil].filter(true) # => [0, 2]\n [0, false, 2, nil].filter(false) # => [false, nil]\n"
41
- email:
23
+ prerelease: false
24
+ version_requirements: *20615240
25
+ description: ! "== Synopsys\n<code>Enumerable#filter</code> - extended <code>Enumerable#select</code>\n\n==
26
+ Examples\nString filter (acts like <code>Enumerable#grep</code>):\n [1, 2, 3, 'ab'].filter(/a/)
27
+ \ # => ['ab']\n [1, 2, 3, '3'].filter('3') # => ['3']\n\nYou
28
+ can pass a <code>Proc</code> or <code>Symbol</code>. Methods and blocks are allowed
29
+ too:\n [1, 2, 3].filter(&:even?) # => [2]\n [1, 2, 3].filter(:even?)
30
+ \ # => [2]\n [1, 2, 4].filter { |num| num.even? } # => [2, 4]\n\n<code>Enumerable#filter</code>
31
+ can match against enumerable items attributes. Like this:\n [1, 2, 3, 4.2].filter
32
+ :to_i => :even? # => [2, 4]\n\nIf the block is supplied, each matching element
33
+ is passed to it, and the block's result is stored in the output array.\n [1, 2,
34
+ 4].filter(&:even?) { |n| n + 1 } # => [3, 5]\n\n<code>Enumerable#filter</code>
35
+ also accepts <code>true</code> or <code>false</code> as argument:\n [0, false,
36
+ 2, nil].filter(true) # => [0, 2]\n [0, false, 2, nil].filter(false) #
37
+ => [false, nil]\n\n<code>Enumerable#filter</code> also supports <code>OR</code>
38
+ operator!\nJust pass many patterns, they will be joined together with <code>OR</code>
39
+ operator.\n [0, 2, 3, 4].filter(:zero?, :odd?) # => [0, 3]"
40
+ email:
42
41
  - amikhailov83@gmail.com
43
42
  executables: []
44
-
45
43
  extensions: []
46
-
47
44
  extra_rdoc_files: []
48
-
49
- files:
45
+ files:
50
46
  - .gitignore
51
47
  - Gemfile
52
48
  - LICENSE
@@ -57,37 +53,28 @@ files:
57
53
  - lib/filter/version.rb
58
54
  - spec/filter_spec.rb
59
55
  - spec/test_helper.rb
60
- has_rdoc: true
61
56
  homepage: https://github.com/take-five/filter
62
57
  licenses: []
63
-
64
58
  post_install_message:
65
59
  rdoc_options: []
66
-
67
- require_paths:
60
+ require_paths:
68
61
  - lib
69
- required_ruby_version: !ruby/object:Gem::Requirement
62
+ required_ruby_version: !ruby/object:Gem::Requirement
70
63
  none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- segments:
75
- - 0
76
- version: "0"
77
- required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
69
  none: false
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
- version: "0"
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
85
74
  requirements: []
86
-
87
75
  rubyforge_project: filter
88
- rubygems_version: 1.3.7
76
+ rubygems_version: 1.8.10
89
77
  signing_key:
90
78
  specification_version: 3
91
79
  summary: Enumerable#filter - extended Enumerable#select combined with Enumerable#collect
92
80
  test_files: []
93
-