TTT
TTT

Reputation: 6906

Hash.delete_if returning removed elements?

From a Hash relations I want to remove some entries and keep the ones I removed in another Hash obj.

I found Hash.delete_if and did:

obj = relations.delete_if{|k,v| v[:value] == 1}

However, instead of returning the ones that are removed, it returns the ones that are not removed.

Is there a method that does that?

Upvotes: 1

Views: 784

Answers (3)

Valery Kvon
Valery Kvon

Reputation: 4496

Try this:

another_hash = {}
relations.delete_if{|k,v| v == 1 ? another_hash[k] = v; true : false}

Upvotes: 2

Andrew Haines
Andrew Haines

Reputation: 6644

You could use the partition method:

{x: 1, y: 0, z: 2, t: 1}.partition {|k, v| v == 1}
# => [[[:x, 1], [:t, 1]], [[:y, 0], [:z, 2]]]

You would then have to turn the results back into hashes, for which you can use the Hash[] method:

{x: 1, y: 0, z: 2, t: 1}.partition{|k, v| v == 1}.map{|h| Hash[h]}
# => [{:x => 1, :t => 1}, {:y => 0, :z => 2}]

So to do what you were asking:

obj, relations = relations.partition{|k, v| v[:value] == 1}.map{|h| Hash[h]}

Upvotes: 3

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230531

I don't know of a built-in method that does this, but building the method yourself is trivial.

def delete_and_return relations, &block
  [relations.reject(&block), relations.select(&block)]
end


relations = {
  a: {value: 1},
  b: {value: 2},
  c: {value: 1},
}



kept, deleted = delete_and_return(relations) {|k,v| v[:value] == 1}

kept # => {:b=>{:value=>2}}
deleted # => {:a=>{:value=>1}, :c=>{:value=>1}}

You can even open Hash class and put the method there.

Upvotes: 0

Related Questions