Я пытаюсь придумать простой способ использования Ruby для скремблирования (или маскировки) некоторых числовых данных, чтобы создать фиктивный набор данных из живых данных. Я хочу сохранить данные как можно ближе к исходному формату (т. Е. Сохранить все нечисловые символы). Номера в данных соответствуют индивидуальным идентификационным номерам, которые (иногда) являются ключами, используемыми в реляционной базе данных. Итак, если числовая строка встречается более одного раза, я хочу последовательно ее сопоставить с тем же (идеально уникальным) значением. После того, как данные были скремблированы, мне не нужно менять скремблирование.Использование Ruby для замены числовых данных с помощью простой hashmap
Я создал функцию скремблирования, которая берет строку и генерирует простой хеш для сопоставления чисел с новыми значениями (функция только отображает числовые цифры и оставляет все остальное как есть). Для дополнительной безопасности каждый раз, когда вызывается функция, ключ восстанавливается. Таким образом, одна и та же фраза будет вызывать два разных результата при каждом вызове функции.
module HashModule
def self.scramble(str)
numHash ={}
0.upto(9) do |i|
numHash[i.to_s]=rand(10).to_s
end
output= String.new(str)
output.gsub!(/\d/) do|d|
d.replace numHash[d]
end
puts "Input: " + str
puts "Hash Key: " + numHash.to_s
puts "Output: " + output
end
end
HashModule.scramble("56609-8 NO PCT 001")
HashModule.scramble("56609-8 NO PCT 001")
Это производит следующий вывод:
Input: 56609-8 NO PCT 001
Hash Key: {"0"=>"9", "1"=>"4", "2"=>"8",
"3"=>"9", "4"=>"4", "5"=>"8",
"6"=>"4", "7"=>"0", "8"=>"2",
"9"=>"1"}
Output: 84491-2 NO PCT 994
Input: 56609-8 NO PCT 001
Hash Key: {"0"=>"2", "1"=>"0", "2"=>"9",
"3"=>"8", "4"=>"4", "5"=>"5",
"6"=>"7", "7"=>"4", "8"=>"2",
"9"=>"0"}
Output: 57720-2 NO PCT 220
Данный набор данных:
PTO NO PC
R5632893423 IP
R566788882-001
NO PCT AMB PTO
NO AMB/CALL IP
A566788882
1655543AACHM IP
56664320000000
00566333-1
Я первый извлечь все числа в массиве. Затем я использую функцию скремблирования, созданную мной для создания хеш-карты замены, например.
{"5632893423"=>"5467106076", "566788882"=>"888299995",
"001"=>"225", "1655543"=>"2466605",
"56664320000000"=>"70007629999999",
"00566333"=>"00699999", "1"=>"3"}
[Кстати, в моем примере, я не нашел способ настоять, что хэш-значения являются уникальными, что актуально в случае, если строка, в которой отображается соответствует уникальному идентификатору в базе данных отношений , как описано выше.]
Я использую gsub на своей исходной строке и заменяю хэш-ключи с помощью скремблированного значения. В коде у меня есть работы, но мне любопытно узнать, как я могу сделать его более кратким. Я понимаю, регенерируя ключ каждый раз, когда вызывается функция, я создаю дополнительную работу. (В противном случае я мог бы просто создать один ключ для замены всех цифр).
Есть ли у кого-нибудь предложения, как я могу это сделать другим способом? (Я новичок в Ruby, поэтому предложения по улучшению моего кода также очень получаются).
input = <<EOS
PTO NO PC
R5632893423 IP
R566788882-001
NO PCT AMB PTO
NO AMB/CALL IP
A566788882
1655543AACHM IP
56664320000000
00566333-1
EOS
module HashModule
def self.scramble(str)
numHash ={}
0.upto(9) do |i|
numHash[i.to_s]=rand(10).to_s
end
output= String.new(str)
output.gsub!(/\d/) do|d|
d.replace numHash[d]
end
return output
end
end
# Extract unique non-null numbers from the input file
numbers = input.split(/[^\d]/).uniq.reject{ |e| e.empty? }
# Create a hash that maps each number to a scrambled value
# Using the function defined above
mapper ={}
numbers.map(&:to_s).each {|x| mapper[x]=HashModule.scramble(x)}
# Create a regexp to find all numbers in input file
re = Regexp.new(mapper.keys.map { |x| Regexp.escape(x) }.join('|'))
# Replace numbers with scrambled values
puts input.gsub(re, mapper)
Приведенный выше код производит следующий вывод:
PTO NO PC
R7834913043 IP
R799922223-772
NO PCT AMB PTO
NO AMB/CALL IP
A799922223
6955509AACHM IP
13330271111111
66166777-6