Построение структуры данных - Хэши Хэшей Хэшей Массивов - PullRequest
0 голосов
/ 09 ноября 2011

На этой неделе на работе у меня была задача разбора файла определенного формата который содержит IP-диапазоны, классифицированные по различным сайтам, областям и Регионы. В основном мне нужен был скрипт для загрузки всей этой информации о местоположении в структура данных, которая позволила бы мне простой способ получить все IP сайтов, областей или регионов для последующей трансформации.

Required data structure:
 data[Region][Area][Site] -> IPs
       Hash   Hash  Hash   Array

Я хотел бы знать, может ли функция «processLocations» быть оптимизирован или, если существует более простой способ достижения желаемых данных состав. особенно при создании переменной региона "Хэши хэшей хэшей массивов".

Надеюсь, что это может помочь кому-то еще в той же ситуации, так что вот моя текущая рабочая копия:

require 'pp'

# Function that processes the content of the locations file and returns
the following structure:
#
# data[Region][Area][Site] -> IPs
#       Hash   Hash  Hash   Array
#
def processLocations (lines)
  sites = Hash.new{|h, k| h[k] = []} # HashOFArray
  area = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)} # HashOFHash
  region = Hash.new{|h,k| h[k]=Hash.new(&h.default_proc)} # HashOFHash

  lines.each do |line|
    next if lines =~ /^#.*/

    # Process IPs range section
    if line =~ /(.*)=([\d|\-|\.]+)/
      #puts "IP: #{$1} - #{$2}"
      sites[$1.chomp.capitalize] << $2
    end

    # Process area section
    if line =~ /(.*)\.area=(.*)/i
      #puts "Area: #{$1} - #{$2}"
      if sites.has_key?($1.chomp.capitalize)

        if (area.has_key?($2.chomp.capitalize) &
area[$2.chomp.capitalize].has_key?($1.chomp.capitalize))
          # The hash exists
          #puts "Adding to an existing hash key more IPs elements to the
array"
          area[$2.chomp.capitalize][$1.chomp.capitalize] <<
sites[$1.chomp.capitalize]
       else
          # The hash does not exist
          #puts "Adding new hash key with new array"
          area[$2.chomp.capitalize][$1.chomp.capitalize] =
sites[$1.chomp.capitalize]
        end

        # Clean site hash
        sites = Hash.new{|h, k| h[k] = []} # HashOFArray
      end
    end

    # Process region section
    if line =~ /(.*)\.region=(.*)/i
      #puts "Region: #{$1} - #{$2}"
      if area.has_key?($1.chomp.capitalize)
        tmp = Hash.new
        tmp = area.dup

        region[$2.chomp.capitalize][$1.chomp.capitalize] =
tmp[$1.chomp.capitalize]
      end
    end
  end
  return region
end

##############
#  MAIN

f = File.open(DATA)
 lines = f.readlines
f.close
data = processLocations(lines)

puts "+data---------------------------------------------------------"
pp data

puts "+data['Asia']-------------------------------------------------"
pp data['Asia']

puts "+data['Asia']['Australia']------------------------------------"
pp data['Asia']['Australia']

puts "+data['Europe-middle east-africa']['France']['Paris']---------"
pp data['Europe-middle east-africa']['France']['Paris']


__END__
Alexandria (ALH)=192.168.6.0-192.168.6.127
Alexandria (ALH).area=Australia
Australia.region=Asia

Altona=192.168.1.192-192.168.1.255
Altona=192.168.2.192-192.168.2.255
Altona.area=Australia

TOKYO VPN=192.168.3.192-192.168.3.255
TOKYO VPN.area=JAPAN
JAPAN.region=Asia

Paris=192.168.4.192-192.168.4.255
Paris.area=France

Rennes=192.168.5.192-192.168.5.255
Rennes.area=France
France.region=EUROPE-MIDDLE EAST-AFRICA

Пример вывода:

# ruby ruby_help.rb
+data---------------------------------------------------------
{"Asia"=>
  {"Australia"=>
    {"Alexandria (alh)"=>["192.168.6.0-192.168.6.127"],
     "Altona"=>["192.168.1.192-192.168.1.255",
"192.168.2.192-192.168.2.255"]},
   "Japan"=>{"Tokyo vpn"=>["192.168.3.192-192.168.3.255"]}},
 "Europe-middle east-africa"=>
  {"France"=>
    {"Paris"=>["192.168.4.192-192.168.4.255"],
     "Rennes"=>["192.168.5.192-192.168.5.255"]}}}
+data['Asia']-------------------------------------------------
{"Australia"=>
  {"Alexandria (alh)"=>["192.168.6.0-192.168.6.127"],
   "Altona"=>["192.168.1.192-192.168.1.255",
"192.168.2.192-192.168.2.255"]},
 "Japan"=>{"Tokyo vpn"=>["192.168.3.192-192.168.3.255"]}}
+data['Asia']['Australia']------------------------------------
{"Alexandria (alh)"=>["192.168.6.0-192.168.6.127"],
 "Altona"=>["192.168.1.192-192.168.1.255",
"192.168.2.192-192.168.2.255"]}
+data['Europe-middle east-africa']['France']['Paris']---------
["192.168.4.192-192.168.4.255"]

С уважением и заранее спасибо за любые предложения,

Себастьян ДАП

1 Ответ

0 голосов
/ 24 ноября 2011

Я согласен с Му, что вы могли бы построить несколько классов, но я думаю, что это должно работать:

def processLocations (lines)
  sites     = Hash.new{|h, k| h[k] = []}
  areas     = Hash.new{|h, k| h[k] = {}}
  regions   = Hash.new{|h, k| h[k] = {}}

  lines.each do |line|

  case line
    # Process IPs range section
    when /(.*)=([\d|\-|\.]+)/
      sites[$1.chomp.capitalize] << $2
    # Process area section
    when /(.*)\.area=(.*)/i
      site_key, area = $1.chomp.capitalize, areas[$2.chomp.capitalize]
      area[site_key] = sites[site_key]
    # Process region section
    when /(.*)\.region=(.*)/i
      area_key, region = $1.chomp.capitalize, regions[$2.chomp.capitalize]
      region[area_key] = areas[area_key]
    when /^#.*/ # do nothing
    else
      # error?
    end
  end
  regions
end
...