Less absolutely horrible way to make sure array 1 only contains elements from array 2?

choices = []
puts “Please make a selection from the following”
#first select the database
db = SQLite3::Database.new(‘data.db’)
#return result as hash so it isn’t an ugly array in an array
db.results_as_hash = true
#now load the list of choices
db.execute(“select entry from table;”) do |name|
#display the list of choices as well as populate an array
choices.push(name[“entry”])
puts name[“entry”]
end

@selections = []
sane = 0
while sane == 0 do
print “Make selections: "
myselections = gets.chop.split(” ")
myselections.each do |path|
@selections.push(path)
end
@selections.each do |selection|
choices.each do |choice|
if choice == selection then sane +=1
end
end
end
if sane != @selections.length then
puts “One of the selections is not available”
sane = 0
@selections = []
end
end

I need to make sure that selections only contains elements from
choices, includes? doesn’t work because it allows for partial matches.
This works but it looks absolutely horrible to me, I am hoping that
someone can share a cleaner looking way to accomplish the same thing.

On Tue, Apr 10, 2012 at 6:44 PM, ruby ismyname [email protected]
wrote:

I need to make sure that myselections only contains elements from
choices, includes? doesn’t work because it allows for partial matches.
This works but it looks absolutely horrible.

I have to agree with that last sentence :slight_smile:

I’m not sure what ‘partial matches’ means in this context but maybe
this will be useful –

1.9.2-p290 :024 > choices = %w[a b c d e f g h i j k]
=> [“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”]
1.9.2-p290 :025 > selections = %w[c h k]
=> [“c”, “h”, “k”]
1.9.2-p290 :026 > bad_selections = %w[a b z]
=> [“a”, “b”, “z”]
1.9.2-p290 :027 > selections.drop_while{|selection| choices.include?
selection }
=> []
1.9.2-p290 :028 > bad_selections.drop_while{|selection|
choices.include? selection }
=> [“z”]
1.9.2-p290 :029 > selections.drop_while{|selection| choices.include?
selection }.count > 0
=> false
1.9.2-p290 :030 > bad_selections.drop_while{|selection|
choices.include? selection }.count > 0
=> true

I’m sure this is also one of those TMTOWTDI cases :slight_smile:

On Wed, Apr 11, 2012 at 4:44 AM, ruby ismyname [email protected]
wrote:

I need to make sure that myselections only contains elements from
choices, includes? doesn’t work because it allows for partial matches.
This works but it looks absolutely horrible.

How about using array difference using the #- method?

choices = [1, 2, 3, 4]
=> [1, 2, 3, 4]
selection_good = [2, 4]
=> [2, 4]
selection_good - choices
=> []
selection_bad = [2, 6]
=> [2, 6]
selection_bad - choices
=> [6]

HTH,
Ammar

On 04/11/2012 03:44 AM, ruby ismyname wrote:

I need to make sure that myselections only contains elements from
choices, includes? doesn’t work because it allows for partial matches.
This works but it looks absolutely horrible.

require ‘set’

valid_choices = Set[:a, :b, :c, :d, :e, :f]

good = Set[:a, :b, :d, :e]
good.subset? choices
=> true

bad = Set[:c, :f, :x, :y]
bad.subset? choices
=> false

Note: you can use Array#to_set to convert an array to a set.

Hi,

I would simply check the choice before pushing it into @choices:

UserError = Class.new StandardError

@selections = []
begin
invalid_choices = []
print "Make selections: "
myselections = gets.chop.split " "
myselections.each do |path|
if choices.include? path # I don’t see any problems with include?
@selections.push path
else
invalid_choices.push path
end
end
raise UserError if @selections.empty?
rescue UserError
puts ‘No valid selections.’
retry
else
unless invalid_choices.empty?
puts “The following selections were invalid: #{invalid_choices.join
', '}”
end
end

On 04/11/2012 01:16 PM, Lars H. wrote:

bad.subset? choices
=> false

Note: you can use Array#to_set to convert an array to a set.

Should be:

good.subset? valid_choices
bad.subset? valid_choices