Phil Ter
It helps your life and without weighing too much on global warming
Sometimes it help you to filter some arrays
This gem let you to filter any kind of arrays to get the item or attributes of selected items. It's short and dynamic which helps to increase the readability. Its trace is a usefull tool for teachers. Performance it's not its field, see the section below.

require 'philter'
# Simple arrays
[1,2,3].philter 1
=> [1]
[1,2,3].philter [2,3]
=> [2,3]
[1,2,3].philter '<= 2'
=> [1,2]
[1,2,3].philter '!= 2'
=> [1,3]
%w[red green blue].philter 'red'
=> ["red"]
%w[red green blue].philter %w(red blue)
=> ["red", "blue"]
# Array of hashes
[
{id: 1, name: 'Mark' },
{id: 2, name: 'Larry' }
].philter id: 1
=> [{:id=>1, :name=>"Mark"}]
[
{id: 1, name: 'Mark' },
{id: 2, name: 'Larry' },
{id: 3, name: 'Bill' }
].philter id: [1,3]
=> [{:id=>1, :name=>"Mark"}, {:id=>3, :name=>"Bill"}]
[
{id: 1, name: 'Mark' },
{id: 2, name: 'Larry' },
{id: 3, name: 'Bill' }
].philter id: '>2'
=> [{:id=>3, :name=>"Bill"}]
# Regular expression
[
{id: 1, name: 'Mark', email: '[email protected]' },
{id: 2, name: 'Larry', email: '[email protected]' },
{id: 3, name: 'Bill', email: '[email protected]' }
].philter email: /@gmail/
=> [{:id=>1, :name=>"Mark", :email=>"[email protected]"}, {:id=>2, :name=>"Larry",:email=>"[email protected]"}]
# Select attributes
[
{id: 1, name: 'Mark', email: '[email protected]' },
{id: 2, name: 'Larry', email: '[email protected]' },
{id: 3, name: 'Bill', email: '[email protected]' }
].philter({email: /@gmail/}, get: :name)
=> ["Mark", "Larry"]
Get the trace with the option debug: true
[
{id: 1, name: 'Mark' },
{id: 2, name: 'Larry' },
{id: 3, name: 'Bill' }
].philter({id: [1,3]}, debug: true)
# You will get a trace
item Hash {:id=>1, :name=>"Mark"}
a. search: Array [:id, [1, 3]]
1.y label: Symbol .2 Hash[:id] == value | 1 == 1 => X
1.y label: Symbol .2 Hash[:id] == value | 1 == 3
item Hash {:id=>2, :name=>"Larry"}
a. search: Array [:id, [1, 3]]
1.y label: Symbol .2 Hash[:id] == value | 2 == 1
1.y label: Symbol .2 Hash[:id] == value | 2 == 3
item Hash {:id=>3, :name=>"Bill"}
a. search: Array [:id, [1, 3]]
1.y label: Symbol .2 Hash[:id] == value | 3 == 1
1.y label: Symbol .2 Hash[:id] == value | 3 == 3 => X
------------------
2 items found
=> [{:id=>1, :name=>"Mark"}, {:id=>3, :name=>"Bill"}]
Rails
Rails return relation objects that must be turned to array
cities = City.all.to_a
City Load (1.0ms) SELECT "cities".* FROM "cities"
=> ... [cut]
cities.philter id: 1
=> [#<City id: 1, name: "Milano", code: "MI", region: "Lombardia", created_at: "2016-05-10 09:07:22", updated_at: "2016-05-10 09:07:22">]
cities.philter code: 'PA'
=> [#<City id: 4, name: "Palermo", code: "PA", region: "Sicilia", created_at: "2016-05-10 09:08:13", updated_at: "2016-05-10 09:08:13">]
cities.philter(region: /\Alomb/i).size
=> 4
Performance
If you need a lot of speed it would be better to use grep when you can or select manually your items.
require 'benchmark'
ar_test = 100.times.map{|n| n}
Benchmark.bmbm do |x|
x.report("philter: ") { 1_000.times { ar_test.philter [1,2] } }
x.report("grep: ") { 1_000.times { ar_test.grep [1,2] } }
end
Rehearsal ---------------------------------------------
philter: 1.872000 0.000000 1.872000 ( 1.859130)
grep: 0.031000 0.000000 0.031000 ( 0.017170)
------------------------------------ total: 1.903000sec
user system total real
philter: 1.826000 0.000000 1.826000 ( 1.834825)
grep: 0.016000 0.000000 0.016000 ( 0.016777)
Benchmark.bmbm do |x|
x.report("philter: ") { 1_000.times { ar_test.philter '< 50' } }
x.report("select: ") { 1_000.times { ar_test.select {|item| item < 50} } }
end
Rehearsal ---------------------------------------------
philter: 3.775000 0.000000 3.775000 ( 3.779718)
select: 0.000000 0.000000 0.000000 ( 0.004455)
------------------------------------ total: 3.775000sec
user system total real
philter: 3.744000 0.000000 3.744000 ( 3.746851)
select: 0.016000 0.000000 0.016000 ( 0.004338)
ar_test = [ {id: 1, name: 'Mark', email: '[email protected]'},
{id: 2, name: 'Bill', email: '[email protected]'},
{id: 3, name: 'Larry', email: '[email protected]'}]
regexp = /\A.+gmail/
Benchmark.bmbm do |x|
x.report("philter: ") { 10_000.times { ar_test.philter email: regexp } }
x.report("select: ") { 10_000.times { ar_test.select {|item| item[:email] =~ regexp} } }
end
Rehearsal ---------------------------------------------
philter: 0.515000 0.000000 0.515000 ( 0.490562)
select: 0.000000 0.000000 0.000000 ( 0.003961)
------------------------------------ total: 0.515000sec
user system total real
philter: 0.468000 0.000000 0.468000 ( 0.473782)
select: 0.000000 0.000000 0.000000 ( 0.003429)
Compatibility
Ruby 1.9+
Install
gem install philter
To use it in a rails project, add to gem file gem 'philter' and run bundle install
To Do
- Add boolean operator to chain of conditions
- Improve performance keeping the operations's trace
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-feature) - Commit your changes (
git commit -am 'I made extensive use of all my creativity') - Push to the branch (
git push origin my-feature) - Create new Pull Request
Testing
bundle install
bundle exec ruby test\philter_test.rb
Found a bug?
Please open an issue.
License
The GNU Lesser General Public License, version 3.0 (LGPL-3.0) See LICENSE file