Поскольку на ваш ответ получен ответ, я предложу альтернативное решение, которое, по моему мнению, должно быть относительно эффективным.Ключ в том, что я создал подсчет хешей для каждого слова в b
перед тем, как перебирать слова в a
.
a = ["dangled", "glad", "gladden", "dogged"]
b = ["gad", "lag", "dad"]
ba = b.map { |w| w.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 } }
#=> [{"g"=>1, "a"=>1, "d"=>1}, {"l"=>1, "a"=>1, "g"=>1}, {"d"=>2, "a"=>1}]
a.select do |w|
ah = w.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
ba.all? { |wh| wh.all? { |c,cnt| ah.fetch(c,0) >= cnt } }
end
#=> ["dangled", "gladden"]
Когда w = "dogged"
в a.select do |w|...
, мыполучить следующее для ah
:
ah = w.each_char.with_object(Hash.new(0)) { |c,h| h[c] += 1 }
#=> {"d"=>2, "o"=>1, "g"=>2, "e"=>1}
Когда wh = {"g"=>1, "a"=>1, "d"=>1}
,
wh.all? { |c,cnt| ah.fetch(c,0) >= cnt }
впервые выполнит
c = "g"
cnt = 1
ah.fetch("g", 0) >= 1 #=> 2 >= 1 => true
Поскольку "g"
проходит тест, мыследующий расчет
c = "a"
cnt = 1
ah.fetch("a", 0) >= 1 #=> 0 >= 1 => false
ah.fetch("a", 0)
возвращает 0
, поскольку ah
не имеет ключа "a"
.
Поскольку h.fetch("a", 0) >= 1
возвращает false
, wh.all? { ... }
возвращаетfalse
, поэтому w = "dogged"
не выбран.
Производительность может быть улучшена путем переупорядочения хэшей в ba
(скажем, путем уменьшения длины слова) и / или переупорядочения пары ключ / значение в каждом элементеba
(уменьшением значений или увеличением частоты в текстах на английском языке ['z'
first, 'e'
last], скажем).