delete - ruby slice array
Ruby Hash cheque es subconjunto? (5)
¿Cómo puedo saber si un hash de Ruby es un subconjunto de (o incluye) otro hash?
Por ejemplo:
hash = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
hash.include_hash?({}) # true
hash.include_hash?({f: 6, c: 3}) # true
hash.include_hash?({f: 6, c: 1}) # false
¿Podría convertir los hashes en sets y realizar la comprobación utilizando el subset?
métodos subset?
y superset?
(o sus respectivos alias <=
y >=
):
require ''set''
hash.to_set.superset?({}.to_set)
# => true
hash.to_set >= {a: 1}.to_set
# => true
{a: 2}.to_set <= hash.to_set
# => false
Actualización : un punto de referencia de las soluciones propuestas:
require ''fruity''
require ''set''
hash = (''aa''..''zz'').zip(''aa''..''zz'').to_h
# {"aa"=>"aa", "ab"=>"ab", ...
find = (''aa''..''zz'').zip(''aa''..''zz'').select { |k, _| k[0] == k[1] }.to_h
# {"aa"=>"aa", "bb"=>"bb", ...
compare(
toro2k: -> { hash.to_set >= find.to_set },
MarekLipka: -> { hash.merge(find) == hash },
CarySwoveland: -> { (find.to_a - hash.to_a).empty? },
ArupRakshit: -> { arr = hash.to_a; find.all? { |pair| arr.include?(pair) } }
)
Resultado:
Running each test 2 times. Test will take about 1 second.
MarekLipka is faster than toro2k by 3x ± 0.1
toro2k is faster than CarySwoveland by 39.99999999999999% ± 10.0%
CarySwoveland is faster than ArupRakshit by 1.9x ± 0.1
Desde Ruby 2.3, también puede hacer lo siguiente para verificar si se trata de un subconjunto
hash = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
{} <= hash # true
{f: 6, c: 3} <= hash # true
{f: 6, c: 1} <= hash # false
La diferencia de matriz parece más fácil:
class Hash
def include_hash?(h)
(h.to_a - to_a).empty?
end
end
h = {a: 1, b: 2}
h.include_hash?({b: 2}) #=> true
h.include_hash?({b: 3}) #=> false
La solución que se me ocurrió utilizar Hash#merge
método de Hash#merge
:
class Hash
def include_hash?(hash)
merge(hash) == self
end
end
hash = {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7}
hash.include_hash?({})
# => true
hash.include_hash?(f: 6, c:3)
# => true
hash.include_hash?(f: 6, c:1)
# => false
Tu puedes hacer :
def include_hash?(hash,subset_hash)
arr = hash.to_a
subset_hash.all? { |pair| arr.include?(pair) }
end