Don Giulio
Don Giulio

Reputation: 3284

ruby: remove a value in an array that is in a hash

I have a hash like this:

a = { a: 1, b: 2, c: [9, 8, 7]}

I need to write a method that given a pair key and value, removes the occurrences of such couple from the hash.

for example, if I pass the couple (:a, 1) I obtain the hash:

a = { b: 2, c: [9, 8, 7]}

if I pass the couple (:c, 8) I obtain the hash:

a = { a: 1, b: 2, c: [9, 7]}

if I pass the couple (:a, 3) I obtain the (unchanged) hash:

a = { a: 1, b: 2, c: [9, 8, 7]}

I'm not sure how to do this, here's what I got so far:

  def remove_criterion (key, value)
    all_params = params.slice(key)
    if all_params[key].class == Array

    else
      params.except(key)
    end
  end

which obviously is incomplete.

thanks for any help,

Upvotes: 0

Views: 113

Answers (3)

Cary Swoveland
Cary Swoveland

Reputation: 110675

I'd do it like this:

def doit(h,k,v)
  return h unless h.include?(k)
  if h[k] == v
    h.delete(k)
  elsif h[k].is_a? Array      
    h[k].delete(v)
  end
  h
end 

h = {a: 1, b: 2, c: [9, 8, 7]}

doit(h,:b,2) #  => {:a=>1,        :c=>[9, 8, 7]}
doit(h,:b,3) #  => {:a=>1, :b=>2, :c=>[9, 8, 7]} 
doit(h,:c,8) #  => {:a=>1, :b=>2, :c=>[9,    7]}
doit(h,:c,6) #  => {:a=>1, :b=>2, :c=>[9, 8, 7]} 
doit(h,:d,1) #  => {:a=>1, :b=>2, :c=>[9, 8, 7]}

Upvotes: 0

Amit Thawait
Amit Thawait

Reputation: 5292

def remove_criterion(key, value)
  params.each do |k,v| 
    if k == key and v == value
      params.delete(key)
    elsif v.class == Array and v.include?(value)
      v.delete(value)
    end
  end
  params
end

Upvotes: 0

Ash Wilson
Ash Wilson

Reputation: 24458

Here's one solution:

def remove_criterion key, value
  params.each_with_object({}) do |pair, h|
    k, v = *pair
    if k == key
      case v
      when Array
        nv = v.reject { |each| each == value }
        h[k] = nv unless nv.empty?
      else
        h[k] = v unless v == value
      end
    else
      h[k] = v
    end
  end
end

Testing it out in irb:

irb(main):007:0> remove_criterion :a, 1
=> {:b=>2, :c=>[9, 8, 7]}
irb(main):008:0> remove_criterion :c, 8
=> {:a=>1, :b=>2, :c=>[9, 7]}
irb(main):009:0> remove_criterion :a, 3
=> {:a=>1, :b=>2, :c=>[9, 8, 7]}

Upvotes: 2

Related Questions