pickup 0.0.4 → 0.0.5
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.
- data/README.md +15 -0
- data/lib/pickup.rb +55 -30
- data/lib/pickup/version.rb +1 -1
- data/spec/pickup/pickup_spec.rb +11 -15
- metadata +3 -3
data/README.md
CHANGED
@@ -67,6 +67,21 @@ pickup.pick
|
|
67
67
|
#=> "minnow"
|
68
68
|
```
|
69
69
|
|
70
|
+
### Random uniq pick
|
71
|
+
|
72
|
+
Also we can pick random uniq items from the list
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
pickup = Pickup.new(pond, uniq: true)
|
76
|
+
pickup.pick(3)
|
77
|
+
#=> [ "gudgeon", "herring", "minnow" ]
|
78
|
+
pickup.pick
|
79
|
+
#=> "herring"
|
80
|
+
pickup.pick
|
81
|
+
#=> "gudgeon"
|
82
|
+
pickup.pick
|
83
|
+
#=> "sturgeon"
|
84
|
+
```
|
70
85
|
|
71
86
|
## Contributing
|
72
87
|
|
data/lib/pickup.rb
CHANGED
@@ -4,18 +4,16 @@ class Pickup
|
|
4
4
|
attr_reader :list, :uniq
|
5
5
|
attr_writer :pick_func
|
6
6
|
|
7
|
-
def initialize(list,
|
7
|
+
def initialize(list, opts={}, &block)
|
8
8
|
@list = list
|
9
|
-
@uniq = uniq
|
9
|
+
@uniq = opts[:uniq] || false
|
10
10
|
@pick_func = block if block_given?
|
11
11
|
end
|
12
12
|
|
13
13
|
def pick(count=1, &block)
|
14
14
|
func = block || pick_func
|
15
15
|
mlist = MappedList.new(list, func, uniq)
|
16
|
-
result = count
|
17
|
-
mlist.random
|
18
|
-
end
|
16
|
+
result = mlist.random(count)
|
19
17
|
count == 1 ? result.first : result
|
20
18
|
end
|
21
19
|
|
@@ -28,44 +26,71 @@ class Pickup
|
|
28
26
|
end
|
29
27
|
|
30
28
|
class MappedList
|
29
|
+
include Enumerable
|
31
30
|
attr_reader :list, :func, :uniq, :max
|
32
31
|
|
33
32
|
def initialize(list, func, uniq=false)
|
34
33
|
@func = func
|
35
34
|
@uniq = uniq
|
36
|
-
@list =
|
35
|
+
@list = list
|
36
|
+
@current_state = 0
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
39
|
+
def each(&blk)
|
40
|
+
item_iterator = next_item
|
41
|
+
item = nil
|
42
|
+
drop = false
|
43
|
+
while true do
|
44
|
+
item ||= item_iterator.call(drop)
|
45
|
+
drop = false
|
46
|
+
if uniq
|
47
|
+
drop = true if yield item
|
48
|
+
item = nil
|
49
|
+
else
|
50
|
+
item = nil unless yield item
|
51
|
+
end
|
52
|
+
end
|
42
53
|
end
|
43
54
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
55
|
+
def next_item
|
56
|
+
dup = list.dup
|
57
|
+
start = 0
|
58
|
+
enum = dup.to_enum
|
59
|
+
item = nil
|
60
|
+
Proc.new do |drop|
|
61
|
+
dup.delete item if drop
|
62
|
+
item = begin
|
63
|
+
enum.next
|
64
|
+
rescue StopIteration => e
|
65
|
+
enum = dup.to_enum
|
66
|
+
enum.next
|
67
|
+
end
|
68
|
+
start += item[1]
|
69
|
+
item[1] = start
|
70
|
+
item
|
49
71
|
end
|
50
|
-
item ||= list.detect{ |k,v| !v[:picked] }
|
51
|
-
raise "No items left" unless item
|
52
|
-
key = item[0]
|
53
|
-
list[key][:picked] = true if uniq
|
54
|
-
key
|
55
72
|
end
|
56
|
-
|
57
|
-
private
|
58
73
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
74
|
+
def random(count)
|
75
|
+
raise "List is shorter then count of items you want to get" if uniq && list.size < count
|
76
|
+
nums = count.times.map{ func.call(rand(max)) }.sort
|
77
|
+
get_random_items(nums)
|
78
|
+
end
|
79
|
+
|
80
|
+
def get_random_items(nums)
|
81
|
+
next_num = Proc.new{ nums.shift }
|
82
|
+
current_num = next_num.call
|
83
|
+
items = []
|
84
|
+
each do |item, counter|
|
85
|
+
break unless current_num
|
86
|
+
val = func.call(counter)
|
87
|
+
if val > current_num
|
88
|
+
items << item
|
89
|
+
current_num = next_num.call
|
90
|
+
true
|
91
|
+
end
|
67
92
|
end
|
68
|
-
|
93
|
+
items
|
69
94
|
end
|
70
95
|
end
|
71
96
|
end
|
data/lib/pickup/version.rb
CHANGED
data/spec/pickup/pickup_spec.rb
CHANGED
@@ -14,40 +14,32 @@ describe Pickup do
|
|
14
14
|
}
|
15
15
|
@func = Proc.new{ |a| a }
|
16
16
|
@pickup = Pickup.new(@list)
|
17
|
-
@pickup2 = Pickup.new(@list, true)
|
17
|
+
@pickup2 = Pickup.new(@list, uniq: true)
|
18
18
|
end
|
19
19
|
|
20
20
|
it "should pick correct ammount of items" do
|
21
21
|
@pickup.pick(2).size.must_equal 2
|
22
|
+
@pickup.pick(10).size.must_equal 10
|
22
23
|
end
|
23
24
|
|
24
25
|
describe Pickup::MappedList do
|
25
26
|
before do
|
26
|
-
@mapped_list = {"selmon"=>{:value=>0, :picked=>false}, "carp"=>{:value=>1, :picked=>false}, "crucian"=>{:value=>5, :picked=>false}, "herring"=>{:value=>8, :picked=>false}, "sturgeon"=>{:value=>14, :picked=>false}, "gudgeon"=>{:value=>22, :picked=>false}, "minnow"=>{:value=>32, :picked=>false}}
|
27
27
|
@ml = Pickup::MappedList.new(@list, @func, true)
|
28
28
|
@ml2 = Pickup::MappedList.new(@list, @func)
|
29
29
|
end
|
30
30
|
|
31
|
-
it "should return right mapped list" do
|
32
|
-
@ml.list.must_equal(@mapped_list)
|
33
|
-
end
|
34
|
-
|
35
31
|
it "should return selmon and then carp and then crucian for uniq pickup" do
|
36
|
-
@ml.
|
37
|
-
@ml.get_random_item(0).must_equal "carp"
|
38
|
-
@ml.get_random_item(0).must_equal "crucian"
|
32
|
+
@ml.get_random_items([0, 0, 0]).must_equal ["selmon", "carp", "crucian"]
|
39
33
|
end
|
40
34
|
|
41
35
|
it "should return selmon 3 times for non-uniq pickup" do
|
42
|
-
@ml2.
|
43
|
-
@ml2.
|
44
|
-
@ml2.
|
36
|
+
@ml2.get_random_items([0]).first.must_equal "selmon"
|
37
|
+
@ml2.get_random_items([0]).first.must_equal "selmon"
|
38
|
+
@ml2.get_random_items([0]).first.must_equal "selmon"
|
45
39
|
end
|
46
40
|
|
47
41
|
it "should return item from the beginning after end of list for uniq pickup" do
|
48
|
-
@ml.
|
49
|
-
@ml.get_random_item(20).must_equal "minnow"
|
50
|
-
@ml.get_random_item(20).must_equal "selmon"
|
42
|
+
@ml.get_random_items([20, 20, 20, 20]).must_equal ["sturgeon", "gudgeon", "minnow", "selmon"]
|
51
43
|
end
|
52
44
|
end
|
53
45
|
|
@@ -55,4 +47,8 @@ describe Pickup do
|
|
55
47
|
items = @pickup2.pick(7)
|
56
48
|
items.uniq.size.must_equal 7
|
57
49
|
end
|
50
|
+
|
51
|
+
it "should raise an exception" do
|
52
|
+
proc{ items = @pickup2.pick(8) }.must_raise RuntimeError
|
53
|
+
end
|
58
54
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pickup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-06-01 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Pickup helps you to pick item from collection by it's weight/probability
|
15
15
|
email:
|
@@ -48,7 +48,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
48
|
version: '0'
|
49
49
|
requirements: []
|
50
50
|
rubyforge_project:
|
51
|
-
rubygems_version: 1.8.
|
51
|
+
rubygems_version: 1.8.24
|
52
52
|
signing_key:
|
53
53
|
specification_version: 3
|
54
54
|
summary: Pickup helps you to pick item from collection by it's weight/probability
|