Question

Using psd.rb gem to return a hash of the properties of a psd file. However I would like to somehow filter the results down just to the font name. Is there a method that can get the value of keys nested within a certain hash e.g the :font hash.

Thanks

Was it helpful?

Solution

require 'json'

# h = <paste object from your gist here, and remove any characters that cause ruby to error>
             
def key_occurences(obj, k)

  # deal with arrays recursively
  return obj.map {|x| key_occurences(x,k) } if obj.is_a?(Array)

  # otherwise assume we have a Hash
  obj.to_a.map do |x|
    return x[1] if x[0] == k
    return key_occurences(x[1], k) if x[1].is_a?(Array) || x[1].is_a?(Hash) #recurse again if our key is itself a Hash or Array
  end.compact
end

puts key_occurences(h, :font).to_json

Your output will be:

[[{"name":"Georgia","sizes":[16.0],"colors":[[255,102,102,102]],"css":"font-family: \"Georgia\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 16.0pt;\ncolor: rgba(102, 102, 102, 255);"},{"name":"AntennaCond-Black","sizes":[16.0],"colors":[[255,89,89,87]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 16.0pt;\ncolor: rgba(89, 89, 87, 255);"},[],[],[],[],[],[],{"name":"ArialMT","sizes":[15.0],"colors":[[255,51,51,51]],"css":"font-family: \"ArialMT\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 15.0pt;\ncolor: rgba(51, 51, 51, 255);"},{"name":"Georgia","sizes":[19.0],"colors":[[255,167,148,72]],"css":"font-family: \"Georgia\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 19.0pt;\ncolor: rgba(167, 148, 72, 255);"},[],[],[]],[[{"name":"MyriadPro-Regular","sizes":[65.0],"colors":[[255,255,255,255]],"css":"font-family: \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 65.0pt;\ncolor: rgba(255, 255, 255, 255);"},{"name":"ArialMT","sizes":[14.0],"colors":[[255,255,255,255]],"css":"font-family: \"ArialMT\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 14.0pt;\ncolor: rgba(255, 255, 255, 255);"},{"name":"Georgia","sizes":[18.0],"colors":[[255,255,255,255]],"css":"font-family: \"Georgia\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 18.0pt;\ncolor: rgba(255, 255, 255, 255);"},[],[],[],[],[],[],[],[],{"name":"AntennaCond-Black","sizes":[18.0,25.0],"colors":[[255,89,89,87]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 18.0pt;\ncolor: rgba(89, 89, 87, 255);"},{"name":"AntennaCond-Black","sizes":[28.0],"colors":[[255,229,42,49]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 28.0pt;\ncolor: rgba(229, 42, 49, 255);"},{"name":"AntennaCond-Black","sizes":[28.0],"colors":[[255,255,255,255]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 28.0pt;\ncolor: rgba(255, 255, 255, 255);"},[],{"name":"AntennaCond-Black","sizes":[28.0],"colors":[[255,255,255,255]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 28.0pt;\ncolor: rgba(255, 255, 255, 255);"},{"name":"AntennaCond-Black","sizes":[15.0],"colors":[[255,229,42,49]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 15.0pt;\ncolor: rgba(229, 42, 49, 255);"},[],{"name":"AntennaCond-Black","sizes":[24.0,39.0],"colors":[[255,255,255,255]],"css":"font-family: \"AntennaCond-Black\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 24.0pt;\ncolor: rgba(255, 255, 255, 255);"},[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],{"name":"Georgia","sizes":[18.0,16.0],"colors":[[255,165,146,70],[255,102,102,102]],"css":"font-family: \"Georgia\", \"Georgia-Italic\", \"MyriadPro-Regular\", \"AdobeInvisFont\";\nfont-size: 18.0pt;\ncolor: rgba(165, 146, 70, 255);"},[],[],[],[],[],[]]],[]]

And you can now further process that for the specific font info you want

EDIT:

Per our comments dicussion, try:

def unwrap(arr)
  return arr if arr[0].is_a?(Hash)
  return nil if arr.is_a?(Array) && arr.size == 0
  unwrap(arr[0])
end

answer = key_occurences(h, :font).map! do |x| 
  unwrap(x)
end.compact!.flatten!

puts answer.map {|x| x[:name]}.uniq

which outputs:

Georgia
AntennaCond-Black
ArialMT
MyriadPro-Regular
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top