Ruby on rails 比较两个哈希值,不管是符号还是字符串,rails
我想比较两个散列和力,使它们相等:Ruby on rails 比较两个哈希值,不管是符号还是字符串,rails,ruby-on-rails,ruby,hash,resque,string-to-symbol,Ruby On Rails,Ruby,Hash,Resque,String To Symbol,我想比较两个散列和力,使它们相等: 一个在键和值上带有符号 第二个只有字符串 e、 g: 这样做不行: > sym_hash == string_hash => false 我首先尝试用符号化字符串\u hash: > string_hash.deep_symbolize_keys => {:id=>58, :locale=>"en-US"} > sym_hash.with_indifferent_access => {"id"=>5
- 一个在键和值上带有符号
- 第二个只有字符串
> sym_hash == string_hash
=> false
我首先尝试用符号化字符串\u hash
:
> string_hash.deep_symbolize_keys
=> {:id=>58, :locale=>"en-US"}
> sym_hash.with_indifferent_access
=> {"id"=>58, "locale"=>:"en-US"}
但是它仍然是错误的,因为sym_hash
仍然在区域设置
变量前面有:
然后我尝试将sym\u散列字符串化:
> string_hash.deep_symbolize_keys
=> {:id=>58, :locale=>"en-US"}
> sym_hash.with_indifferent_access
=> {"id"=>58, "locale"=>:"en-US"}
但当我测试是否相等时,出于同样的原因,它仍然是false
编辑
为了回答关于为什么我希望这些散列在这里相等的许多评论,我将解释我正在尝试做什么
我用它来管理我的工作。现在,我想做一个类,以避免运行相同的*作业,或同时排队两次
(相同:对于我来说,相同的作业是具有相同参数的作业,例如,我希望能够两次enqueu具有不同ID的相同作业。)
因此,我是一个使用插件的用户,到目前为止,我能够知道作业何时运行。此外,当我使用set
保存参数时,我注意到写入Redis
的消息(因为resque status使用Redis跟踪作业的状态)没有用符号正确保存
这是我的班级:
# This class is used to run thread-lock jobs with Resque.
#
# It will check if the job with the exact same params is already running or in the queue.
# If the job is not finished, it will returns false,
# otherwise, it will run and returns a the uuid of the job.
#
class JobLock
def self.run(obj, params = {})
# Get rid of completed jobs.
Resque::Plugins::Status::Hash.clear_completed
# Check if your job is currently running or is in the queue.
if !detect_processing_job(obj, params)
job_uuid = obj.create(params)
Resque::Plugins::Status::Hash.set(job_uuid,
job_name: obj.to_s,
params: params)
job_uuid
else
false
end
end
def self.detect_processing_job(obj, params = {})
Resque::Plugins::Status::Hash.statuses.detect do |job|
job['job_name'] == obj.to_s && compare_hashes(job['params'], params)
end
end
def self.compare_hashes(string_hash, sym_hash)
[sym_hash, string_hash].map do |h|
h.map { |kv| kv.map(&:to_s) }.sort
end.reduce :==
end
end
下面是我如何使用它:
JobLock.run(MyAwesomeJob, id: 58, locale: :"en-US")
正如你所看到的,我使用了@mudasobwa的答案,但我希望有一个更简单的方法来实现我正在尝试的目标 以下版本用作PHP强制平等:
[sym_hash, string_hash].map do |h|
h.map { |kv| kv.map(&:to_s) }.sort
end.reduce :==
顺便说一句,这不仅仅是因为我尊重有智能手机的人。在宽度为80的端子上,这是一个完美的单线
要仅将符号强制为字符串,保留要与其字符串表示形式区分的数字,请执行以下操作:
[sym_hash, string_hash].map do |h|
h.map { |kv| kv.map { |e| e.is_a?(Symbol) ? e.to_s : e } }.sort
end.reduce :==
以下版本用作PHP强制相等:
[sym_hash, string_hash].map do |h|
h.map { |kv| kv.map(&:to_s) }.sort
end.reduce :==
顺便说一句,这不仅仅是因为我尊重有智能手机的人。在宽度为80的端子上,这是一个完美的单线
要仅将符号强制为字符串,保留要与其字符串表示形式区分的数字,请执行以下操作:
[sym_hash, string_hash].map do |h|
h.map { |kv| kv.map { |e| e.is_a?(Symbol) ? e.to_s : e } }.sort
end.reduce :==
sym\u hash
中的locale
值是一个符号:“en-US”
,
而string\u hash
中的locale
的值是字符串。
所以他们是不平等的
现在如果你这样做了:
sym_hash = {:id=>58, :locale=>"en-US"}
string_hash = {"id"=>58, "locale"=>"en-US"}
string_hash.symbolize_keys!
sym_hash == string_hash
=> true
sym\u hash
中的locale
值是一个符号:“en-US”
,
而string\u hash
中的locale
的值是字符串。
所以他们是不平等的
现在如果你这样做了:
sym_hash = {:id=>58, :locale=>"en-US"}
string_hash = {"id"=>58, "locale"=>"en-US"}
string_hash.symbolize_keys!
sym_hash == string_hash
=> true
您可以尝试将这两个哈希转换为JSON,然后比较它们:
require 'json'
# => true
sym_hash = {:id=>58, :locale=>:"en-US"}
# => {:id=>58, :locale=>:"en-US"}
string_hash = {"id"=>58, "locale"=>"en-US"}
# => {"id"=>58, "locale"=>"en-US"}
sym_hash.to_json == string_hash.to_json
# => true
您可以尝试将这两个哈希转换为JSON,然后比较它们:
require 'json'
# => true
sym_hash = {:id=>58, :locale=>:"en-US"}
# => {:id=>58, :locale=>:"en-US"}
string_hash = {"id"=>58, "locale"=>"en-US"}
# => {"id"=>58, "locale"=>"en-US"}
sym_hash.to_json == string_hash.to_json
# => true
这个怎么样
require 'set'
def sorta_equal?(sym_hash, str_hash)
return false unless sym_hash.size == str_hash.size
sym_hash.to_a.to_set == str_hash.map { |pair|
pair.map { |o| o.is_a?(String) ? o.to_sym : o } }.to_set
end
sym_hash= {:id=>58, :locale=>:"en-US"}
sorta_equal?(sym_hash, {"id"=>58, "locale"=>"en-US"}) #=> true
sorta_equal?(sym_hash, {"locale"=>"en-US", "id"=>58 }) #=> true
sorta_equal?(sym_hash, {"id"=>58, "local"=>"en-US", "a"=>"b" }) #=> false
sorta_equal?(sym_hash, {"id"=>58, "lacole"=>"en-US"}) #=> false
sorta_equal?(sym_hash, {"id"=>58, [1,2,3]=>"en-US"}) #=> false
sorta_equal?({}, {}) #=> true
class A; end
a = A.new
sorta_equal?({:id=>a, :local=>:b}, {"id"=>a, "local"=>"b"}) #=> true
这个怎么样
require 'set'
def sorta_equal?(sym_hash, str_hash)
return false unless sym_hash.size == str_hash.size
sym_hash.to_a.to_set == str_hash.map { |pair|
pair.map { |o| o.is_a?(String) ? o.to_sym : o } }.to_set
end
sym_hash= {:id=>58, :locale=>:"en-US"}
sorta_equal?(sym_hash, {"id"=>58, "locale"=>"en-US"}) #=> true
sorta_equal?(sym_hash, {"locale"=>"en-US", "id"=>58 }) #=> true
sorta_equal?(sym_hash, {"id"=>58, "local"=>"en-US", "a"=>"b" }) #=> false
sorta_equal?(sym_hash, {"id"=>58, "lacole"=>"en-US"}) #=> false
sorta_equal?(sym_hash, {"id"=>58, [1,2,3]=>"en-US"}) #=> false
sorta_equal?({}, {}) #=> true
class A; end
a = A.new
sorta_equal?({:id=>a, :local=>:b}, {"id"=>a, "local"=>"b"}) #=> true
最后,为了回答我的问题,我不需要强制在散列之间进行比较。我使用Marshal
来避免问题
class JobLock
def self.run(obj, params = {})
# Get rid of completed jobs.
Resque::Plugins::Status::Hash.clear_completed
# Check if your job is currently running or is in the queue.
if !detect_processing_job(obj, params)
job_uuid = obj.create(params)
Resque::Plugins::Status::Hash.set(job_uuid,
job_name: obj.to_s,
params: Marshal.dump(params))
job_uuid
else
false
end
end
def self.detect_processing_job(obj, params = {})
Resque::Plugins::Status::Hash.statuses.detect do |job|
job['job_name'] == obj.to_s && Marshal.load(job['params']) == params
end
end
end
不管怎样,我把这个问题放在这里,因为它可能会在将来帮助一些人…最后,为了回答我的问题,我不需要强制在散列之间进行比较。我使用Marshal
来避免问题
class JobLock
def self.run(obj, params = {})
# Get rid of completed jobs.
Resque::Plugins::Status::Hash.clear_completed
# Check if your job is currently running or is in the queue.
if !detect_processing_job(obj, params)
job_uuid = obj.create(params)
Resque::Plugins::Status::Hash.set(job_uuid,
job_name: obj.to_s,
params: Marshal.dump(params))
job_uuid
else
false
end
end
def self.detect_processing_job(obj, params = {})
Resque::Plugins::Status::Hash.statuses.detect do |job|
job['job_name'] == obj.to_s && Marshal.load(job['params']) == params
end
end
end
无论如何,我把这个问题放在这里,因为它可能会在将来帮助一些人…这些散列是不同的,在这种情况下,我想修改它们以使它们相似。它不是一个线性函数(除非你用一个方法包装它),但是你可以循环散列,并根据它们的方法将值与
方法进行比较。如果你愿意,我可以提供一个代码示例。我想要一个也可以比较空哈希的通用方法。所以我不想在每个散列上循环。但是请试一试!1.从您的示例中可以看出,对于一个散列(sym\u hash
),键都是符号,没有值是字符串,而对于另一个散列(string\u hash
),所有键都是字符串,没有值是符号。对的(那和你说的不一样。如果string\u hash
中作为字符串的所有键和值都转换为符号,则需要知道这两个哈希是否相等。对的3.请澄清“强制它们相等”是什么意思。这些散列是不同的,在这种情况下,我想修改它们以使它们相似。它不是一条直线(除非用方法包装),但您可以循环散列,并根据它们的与\u s
方法比较值。如果你愿意,我可以提供一个代码示例。我想要一个也可以比较空哈希的通用方法。所以我不想在每个散列上循环。但是请试一试!1.从您的示例中可以看出,对于一个散列(sym\u hash
),键都是符号,没有值是字符串,而对于另一个散列(string\u hash
),所有键都是字符串,没有值是符号。对的(那和你说的不一样。如果string\u hash
中作为字符串的所有键和值都转换为符号,则需要知道这两个哈希是否相等。对的3.请澄清你所说的“强迫他们平等”是什么意思。泰,是的,我不管怎样都不在乎一句台词。所以它不存在一种自动转换sym哈希键和值的方法?我希望它不存在。你希望吗?为什么?我这里的问题是,我将第一个散列放入reddis缓存,但ofc reddis不处理符号参数。也许我的问题更多的是XY问题,我希望是因为Rails扩展基本上扼杀了自己编写代码的能力。Redis可以完美地处理AFAICT符号。如果sym_hash
的值未定义,则#1也不起作用。我建议#1↷泰,是的,反正我不在乎一条客轮。所以它不存在一种自动转换sym哈希键和值的方法?我希望它不存在。你希望吗?为什么?我这里的问题是,我将第一个散列放入reddis缓存,但ofc reddis不手动