如何连接哈希值和字符串

时间:2019-02-06 04:21:28

标签: ruby string

我试图将我的哈希值作为连接字符串写入变量。

original_string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
cipher_key = "honeyL"
message_string = "hEllo world"

deleted_string = original_string.delete!(cipher_key)

altered_string = cipher_key + deleted_string

encryption_hash = Hash.new

i = 0
while(i < original_string.length) 
  encryption_hash [original_string[i]] = altered_string[i].to_s
  i += 1
end

encrypted_message = ""
count = 0

while(count < message_string.length)
  if(message_string[count] == " ")
    encrypted_message << message_string[count]
  else
    encrypted_message << encryption_hash[message_string[count]] 
  end
  count += 1
end

puts encrypted_message

我在第24行有问题,但我不知道为什么。如果我使用encryption_hash[original_string[count]]而不是encryption_hash[message_string[count]],那么它将起作用。但是我不知道为什么。请解释。

2 个答案:

答案 0 :(得分:2)

因此这应该有助于您走上正确的道路。我不确定您项目的预期结果是100%不确定的,但是这里有一个简短的原创与重写以及对发生的事情的解释。

原始(带注释)

original_string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
cipher_key = "honeyL"
message_string = "hEllo world"

# Using the delete! method is actually altering the original_string in memory. You want to use the plane delete method.
deleted_string = original_string.delete!(cipher_key)

altered_string = cipher_key + deleted_string

# This is a fair amount of code for a simple mapping
encryption_hash = Hash.new

i = 0
while(i < original_string.length) 
  encryption_hash [original_string[i]] = altered_string[i].to_s
  i += 1
end

encrypted_message = ""
count = 0

# Because you deleted the message characters from the original_string BEFORE creating you encryption_hash, you're getting null value on the look up.
while(count < message_string.length)
  if(message_string[count] == " ")
    encrypted_message << message_string[count]
  else
    encrypted_message << encryption_hash[message_string[count]] 
  end
  count += 1
end

puts encrypted_message

重写

base_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
message = 'hEllo world'
key = 'honeyL'

# Using delete instead of delete!
altered_str = key + base_str.delete(key)

# Zip together characters and create hash from grouped array
encryption_hash = Hash[base_str.chars.zip(altered_str.chars)]
encryption_hash[' '] = ' '

encrypted_message = ''

# Loop through non-inclusive range concatenating encrypted values to string
for i in 0...message.length
  encrypted_message << encryption_hash[message[i]]
end

puts encrypted_message

更新

我浏览了一些建议的迭代器,以查看哪个迭代器的性能最佳,并且所有迭代器都相对相同(使用8,145,000个字符消息):

  encrypted_message = message.gsub(/./) { |chr| encryption_hash[chr] }
  # {"ruby":"2.3.0","elapsed_time":3.24,"garbage_collection":"on","memory_used":"8 MB","garbage_collection_count":456}

  message.each_char { |m| encrypted_message << encryption_hash[m] }
  # {"ruby":"2.3.0","elapsed_time":2.06,"garbage_collection":"on","memory_used":"8 MB","garbage_collection_count":456}

  (0...message.length).each { |i| encrypted_message << encryption_hash[message[i]]  }
  # {"ruby":"2.3.0","elapsed_time":2.21,"garbage_collection":"on","memory_used":"8 MB","garbage_collection_count":456}

  for i in 0...message.length
    encrypted_message << encryption_hash[message[i]]
  end
  # {"ruby":"2.3.0","elapsed_time":2.21,"garbage_collection":"on","memory_used":"8 MB","garbage_collection_count":456}

也就是说,我发现gsub可以将哈希作为其第二个参数,用于匹配字符上的替换映射。这是在同一个球场上进行的。

  message.gsub!(/[a-zA-Z]/, encryption_hash)
  # {"ruby":"2.3.0","elapsed_time":2.45,"garbage_collection":"on","memory_used":"8 MB","garbage_collection_count":388}

最终,我认为这是最好的解决方案。原因是它不需要对原始字符串进行预格式化,也不会丢失任何未映射的值。例如,在原始答案中,所有标点符号或数字都将被省略和丢失。使用这种gsub方法,您只能加密要加密的字符集,其余部分保持不变。

这简化了解决方案:

base_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
message = 'hEllo world'
key = 'honeyL'

altered_str = key + base_str.delete(key)

encryption_hash = Hash[base_str.chars.zip(altered_str.chars)]

message.gsub!(/[a-zA-Z]/, encryption_hash)

puts message

答案 1 :(得分:1)

您在此行遇到错误:

encrypted_message << encryption_hash[message_string[count]] 

因为message_string[count]从您的h返回hEllo world,但是您的encryption_hash是没有h键的哈希值,也没有{{1 }}个字符。

呼叫honeyL时,original_string.delete!(cipher_key)突变了delete!,从original_string中删除了6个字符

将原始字符串替换为消息字符串的原因起作用:

cipher_key

在您的示例中,pry >> original_string => "abcdfgijklmpqrstuvwxzABCDEFGHIJKMNOPQRSTUVWXYZ" pry >> message_string => "hEllo world" 为0(您在第一次迭代中),因此它正在寻找0的索引。 count的0索引是original_string,它存在于您的a中。 encryption_hash的0索引是message_string,在您的h中不存在。

我不确定解决方案是什么,因为我不确定预期的结果。但这就是原因所在。要对其进行调试,可以尝试encryption_hash,然后在ruby文件的顶部添加:

gem install pry pry-byebug

然后,在require 'pry' require 'pry-byebug 语句后的新行中,添加else。运行您的脚本,它将在该行“停止”。您可以使用binding.pry检查此时的所有变量。

使用puts退出撬动,然后使用exit重置代码中停止位置的视图。您还可以使用whereami来评估一行。

pry example