从唯一的ruby数组

时间:2015-04-28 21:57:18

标签: ruby-on-rails ruby

我知道这是一个在黑暗中的镜头,但它在这里。我一直在尝试使用类似于下面的ruby来构建一个无序列表,但这里有一个问题:我从API接收的数据不是一种易于解析的格式。

我知道我将不得不使用递归,但我不确定如何将其正确转换为嵌套(父 - 子)红宝石哈希。

对于解决我的问题的任何建议或参考资料将不胜感激。感谢您抽出时间阅读此问题。

Ruby Array

[ [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12.mp4", 3450211337 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\video VC-1 BD TEST SAMPLE\\video VC-1 BD SAMPLE.mkv", 249150757 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\English.idx", 62582 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\French.idx", 43725 ],
]

所需的无序列表

<ul>
  <li>Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12
    <ul>
      <li>Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12.mp4 - (3450211337)</li>
    </ul>
    <ul>
      <li>video VC-1 BD TEST SAMPLE</li>
      <ul>
        <li>video VC-1 BD SAMPLE.mkv - (249150757)</li>
      </ul>  
    </ul>
    <ul>
      <li>subs idx
        <ul>
         <li>English.idx - (62582)</li>
         <li>French.idx - (43725)</li>
        </ul>  
      </li>
    </ul>
   </li>
</ul>

只是想感谢大家的指导和帮助。我使用了帮助来启动我网站上torrent文件的树状视图:moviemagnet.net

tree view of torrent files

2 个答案:

答案 0 :(得分:2)

以下块将生成遵循上述布局的哈希。它不是递归的,只是深度为“1”。我希望这已经足够了。

array = [ [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12.mp4", 3450211337 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\video VC-1 BD TEST SAMPLE\\video VC-1 BD SAMPLE.mkv", 249150757 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\English.idx", 62582 ],
  [ " Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\French.idx", 43725 ]]
hash={}

array.each do |i|
  j=i.join(', ').split('\\').map(&:strip) # split at '//'
  k=j[0] 
  j.shift
  if hash[k].blank?
    hash[k]=j
  else
    l = hash[k].map{|v| v[0]} # check the first element of each item in the array
    p = l.index j[0]
    if p.nil? # see if current item already there
      hash[k] << j
    else
      j.shift
      hash[k][p][1] = Array(hash[k][p][1]) # if it's string, make it array
      hash[k][p][1] << j.join(" ")
    end
  end
end

# hash
{"Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12"=>
    [
        "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12.mp4, 3450211337", 
        ["video VC-1 BD TEST SAMPLE", "video VC-1 BD SAMPLE.mkv, 249150757"], 
        ["subs idx", ["English.idx, 62582", "French.idx, 43725"]]
    ]
}

答案 1 :(得分:2)

下面的递归方法适用于任意数量的级别。此代码生成一个哈希,您可以根据需要轻松地格式化文本。

<强>代码

def doit(a)
   return a.first if a.size == 1
   sz = common_prefix_size(a)
   {a.first.first[0, sz]=>
     a.map { |b| [b.first[sz..-1], b.last] }
      .group_by { |b| b.first[0] }
      .values
      .map { |b| doit(b) } }
end

def common_prefix_size(a)
  i = 0
  loop do
    return i if (a.map { |b| b.first[i] }.uniq.size > 1) || a.first.first == nil
    i += 1
  end
end

示例

除了第三个元素&#34; Ruby Array&#34;之外,我已经淘汰了领先的空间。 (假设他们是拼写错误)。

a = [ [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12.mp4", 3450211337 ],
      [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\video VC-1 BD TEST SAMPLE\\video VC-1 BD SAMPLE.mkv", 249150757 ],
      [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\English.idx", 62582 ],
      [ "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\subs idx\\French.idx", 43725 ],
    ]

doit(a)
  #=> {"Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\"=>
  #     [ ["Lost in Translation...tomcat12.mp4", 3450211337],
  #       ["video VC-1...SAMPLE.mkv", 249150757], 
  #       {"subs idx\\"=>
  #         [ ["English.idx", 62582],
  #           ["French.idx", 43725]
  #         ]
  #       }
  #     ]
  #   } 

<强>解释

首先考虑辅助方法common_prefix_size(a)。这需要一个两元素数组的数组作为参数。每个双元素数组的第一个元素是一个字符串。此方法返回最大整数n,使所有字符串的第一个n字符相等。 n可以在0和最短字符串的大小之间。请注意,如果s.size => n为字符串ss[m] => nilm >= n

对于上面的a

common_prefix_size(a) #=> 55

表示公共字符串是:

a.first.first[0,55]
  #=> "Lost in Translation 2003 BDRip 1080p AAC x264-tomcat12\\"

doit返回a.first a.size == 1,其中a,其参数是初始a的子数组,除了第一个如此多的字符已删除每个字符串,如下所述。

如果a.size > 1doit获取sz = common_prefix_size以确定它将返回的哈希的唯一键,则该键为:

a.first.first[0, sz]

然后将a映射到一个数组中,每个元素的第一个元素是通过删除第一个sz个字符获得的字符串。然后将获得的数组的元素分组在每个元素的第一个元素的第一个字符(一个字符串)上。 (使a的元素成为双元素数组肯定会使这种解释变得复杂。:-))。该分组是散列,其键是上面提到的不同的第一个字母。然后将此散列的每个值(在删除字符串的开头之后的a的子数组)传递给doit。呼!

我很欣赏这种解释可能需要二读。