2016-06-17 126 views
0

收集目标键的值到数组我有一个这样的文件:红宝石:从嵌套哈希

$urls = [ 
     {name:'Venture Capitals', 
     sites: [ 
      'http://blog.ycombinator.com/posts.atom', 
      'http://themacro.com/feed.xml', 
      'http://a16z.com/feed/', 
      'http://firstround.com/review/feed.xml', 
      'http://www.kpcb.com/blog.rss', 
      'https://library.gv.com/feed', 
      'http://theaccelblog.squarespace.com/blog?format=RSS', 
      'https://medium.com/feed/accel-insights', 
      'http://500.co/blog/posts/feed/', 
      'http://feeds.feedburner.com/upfrontinsights?format=xml', 
      'http://versionone.vc/feed/', 
      'http://nextviewventures.com/blog/feed/', 
     ]}, 

     {name:'Companies and Groups', 
     sites: [ 
      {name:'Product Companies', 
      sites: [ 
       'https://m.signalvnoise.com/feed', 
       'http://feeds.feedburner.com/insideintercom', 
       'http://www.kickstarter.com/blog.atom', 
       'http://blog.invisionapp.com/feed/', 
       'http://feeds.feedburner.com/bufferapp', 
       'https://open.buffer.com/feed/', 
       'https://blog.asana.com/feed/', 
       'http://blog.drift.com/rss.xml', 
       'https://www.groovehq.com/blog/feed',]}, 
      {name:'Consulting Groups, Studios', 
      sites: [ 
       'http://svpg.com/articles/rss', 
       'http://www.thoughtworks.com/rss/insights.xml', 
       'http://zurb.com/blog/rss',]}, 
      {name:'Communities', 
      sites: [ 
       'http://alistapart.com/main/feed', 
       'https://www.mindtheproduct.com/feed/',]}, 
     ]}, 


    ] 

我已经组织了$url分成不同的组。现在我想提取所有的url(链接sites),我应该怎么做?

主要问题是,sites内有sites,如上面的文件所示。

我的问题是:

  1. 我使用一个适当的文件结构保存这些链接? (数组内的数组)。如果不是,那么保存和分组它们的好方法是什么?

  2. 如何将所有网址提取到平展数组中?所以我可以稍后遍历列表。

我可以手动做到这一点,就像下面显示的代码一样。

sites = [] 
    $urls.each do |item| 
    item[:sites].each do |sub_item| 
     if sub_item.is_a?(Hash) 
     sites.concat sub_item[:sites] 
     else 
     sites.append sub_item 
     end 
    end 
    end 

    File.open('lib/flatten_sites.yaml', 'w') { |fo| fo.puts sites.to_yaml } 

但我只是觉得这是不好的代码。

在这个特定情况下的另一个选择是收集所有的sites属性,但我觉得这也是非常有限的,并且在某些其他情况下可能无法帮助。

回答

3

如果你有Hash,您可以使用此递归方法

输入

urls = [ 
    { 
    :name => 'Venture Capitals', 
    :sites => [ 
     'http://blog.ycombinator.com/posts.atom', 
     'http://themacro.com/feed.xml', 
     'http://a16z.com/feed/', 
     'http://firstround.com/review/feed.xml', 
     'http://www.kpcb.com/blog.rss', 
     'https://library.gv.com/feed', 
     'http://theaccelblog.squarespace.com/blog?format=RSS', 
     'https://medium.com/feed/accel-insights', 
     'http://500.co/blog/posts/feed/', 
     'http://feeds.feedburner.com/upfrontinsights?format=xml', 
     'http://versionone.vc/feed/', 
     'http://nextviewventures.com/blog/feed/', 
    ] 
    }, 
    { 
    :name => 'Companies and Groups', 
    :sites => [ 
     { 
     :name => 'Product Companies', 
     :sites => [ 
      'https://m.signalvnoise.com/feed', 
      'http://feeds.feedburner.com/insideintercom', 
      'http://www.kickstarter.com/blog.atom', 
      'http://blog.invisionapp.com/feed/', 
      'http://feeds.feedburner.com/bufferapp', 
      'https://open.buffer.com/feed/', 
      'https://blog.asana.com/feed/', 
      'http://blog.drift.com/rss.xml', 
      'https://www.groovehq.com/blog/feed',] 
     }, 
     { 
     :name => 'Consulting Groups, Studios', 
     :sites => [ 
      'http://svpg.com/articles/rss', 
      'http://www.thoughtworks.com/rss/insights.xml', 
      'http://zurb.com/blog/rss',] 
     }, 
     { 
     :name => 'Communities', 
     :sites => [ 
      'http://alistapart.com/main/feed', 
      'https://www.mindtheproduct.com/feed/',] 
     } 
    ] 
    } 
] 

方法

def get_all_sites(data) 
    data[:sites].map { |r| Hash === r ? get_all_sites(r) : r } 
end 

urls.map { |r| get_all_sites(r) }.flatten 

输出

[ 
    "http://blog.ycombinator.com/posts.atom", 
    "http://themacro.com/feed.xml", 
    "http://a16z.com/feed/", 
    "http://firstround.com/review/feed.xml", 
    "http://www.kpcb.com/blog.rss", 
    "https://library.gv.com/feed", 
    "http://theaccelblog.squarespace.com/blog?format=RSS", 
    "https://medium.com/feed/accel-insights", 
    "http://500.co/blog/posts/feed/", 
    "http://feeds.feedburner.com/upfrontinsights?format=xml", 
    "http://versionone.vc/feed/", 
    "http://nextviewventures.com/blog/feed/", 
    "https://m.signalvnoise.com/feed", 
    "http://feeds.feedburner.com/insideintercom", 
    "http://www.kickstarter.com/blog.atom", 
    "http://blog.invisionapp.com/feed/", 
    "http://feeds.feedburner.com/bufferapp", 
    "https://open.buffer.com/feed/", 
    "https://blog.asana.com/feed/", 
    "http://blog.drift.com/rss.xml", 
    "https://www.groovehq.com/blog/feed", 
    "http://svpg.com/articles/rss", 
    "http://www.thoughtworks.com/rss/insights.xml", 
    "http://zurb.com/blog/rss", 
    "http://alistapart.com/main/feed", 
    "https://www.mindtheproduct.com/feed/" 
] 

我希望这有助于

2

该解决方案类似于卢卡斯Baliak提出,但使用更适合Proc,而不是冗余method(适用于一级的嵌套的任何金额):

deep_map = ->(data) do 
    data[:sites].flat_map { |r| r.is_a?(String) ? r : deep_map.(r) } 
end 
urls.flat_map(&deep_map) 
+0

RLY不错拉姆达。如果我理解的很好,那'deep_map。(r)'和'deep_map.call(r)'是一样的吗? –

+0

@LukasBaliak正好。 – mudasobwa

+0

恐怕'Proc'对我来说有点难... – cqcn1991