【发布时间】:2020-04-22 12:10:19
【问题描述】:
背景
我有一组嵌套哈希,它们提供一组参数来定义应用程序行为:
custom_demo_options: {
verticals: {
fashion: true,
automotive: false,
fsi: false
},
channels: {
b2b: true,
b2c: true
}
}
website_data: {
verticals: {
fashion: {
b2b: {
code: 'luma_b2b',
url: 'b2b.luma.com'
},
b2c: {
code: 'base',
url: 'luma.com'
}
}
}
}
在custom_demo_options 散列中所做的选择与存储在website_data 散列中的数据相关,并用于从中返回值:
data = []
collection = {}
custom_demo_options[:verticlas].each do |vertical_name, vertical_choice|
# Get each vertical selection
if vertical_choice == true
# Loop through the channels for each selected vertical
custom_demo_options[:channels].each do |channel_name, channel_choice|
# Get each channel selection for each vertical selection
if channel_choice == true
# Loop through the website data for each vertical/channel selection
website_data[:verticals].each do |site_vertical, vertical_data|
# Look at the keys of the [:website_data][:verticals] hash
# If we have a vertical selection that matches a website_data vertical...
if site_vertical == vertical_name
# For each website_data vertical collection...
vertical_data.each do |vertical_channel, channel_value|
# If we have a matching channel in the collection...
if vertical_channel == channel_name
# Add the channel's url and code to the collection hash
collection[:url] = channel_value[:url]
collection[:code] = channel_value[:code]
# Push the collection hash(es) onto the data array
data.push(collection)
}
}
}
}
}
}
}
}
推送到数据数组的数据最终用于创建如下的nginx映射定义:
map $http_host $MAGE_RUN_CODE {
luma.com base;
b2b.luma.com luma_b2b;
}
作为哈希之间关系的示例,如果用户设置custom_demo_options[:channels][:b2b] tofalse, the b2b code/url pair stored in thewebsite_data`哈希将从nginx块中删除:
map $http_host $MAGE_RUN_CODE {
luma.com base;
}
问题
上面的代码有效,但我知道它的效率非常低。我对 ruby 比较陌生,但我认为这很可能是一个逻辑挑战,而不是特定于语言的挑战。
我的问题是,连接这些哈希而不是像我一样使用循环的正确方法是什么?我在hash.select 上做了一些阅读,似乎这可能是最好的路线,但我想知道:我应该考虑其他方法来优化此操作吗?
更新
我已经能够实施第一个建议(再次感谢发帖者);但是,我认为第二种解决方案将是更好的方法。一切都按描述工作;但是,我的数据结构略有变化,虽然我了解解决方案的作用,但我无法相应地进行调整。这是新的结构:
custom_demo_options = {
verticals: {
fashion: true,
automotive: false,
fsi: false
},
channels: {
b2b: true,
b2c: true
},
geos: [
'us_en'
]
}
website_data = {
verticals: {
fashion: {
us_en: {
b2b: {
code: 'luma_b2b',
url: 'b2b.luma.com'
},
b2c: {
code: 'base',
url: 'luma.com'
}
}
}
}
}
所以,我在哈希中添加了另一个级别,:geo。
我已经尝试适应第二种解决方案如下:
class CustomOptionsMap
attr_accessor :custom_options, :website_data
def initialize(custom_options, website_data)
@custom_options = custom_options
@website_data = website_data[:verticals]
end
def data
verticals = selected_verticals
channels = selected_channels
geos = selected_geos
# I know this is the piece I'm not understanding. How to map channels and geos accordingly.
verticals.map{ |vertical| @website_data.fetch(vertical).slice(*channels) }
end
private
def selected_geos
@custom_options[:geos].select{|_,v| v } # I think this is correct, as it extracts the geo from the array and we don't have additional keys
end
def selected_verticals
@custom_options[:verticals].select{|_,v| v }.keys
end
def selected_channels
@custom_options[:channels].select{|_,v| v }.keys
end
end
demo_configuration = CustomOptionsMap.new(custom_demo_options, website_data)
print demo_configuration.data
非常感谢任何关于我在地图声明方面缺少的指导。
【问题讨论】:
-
虽然这两个答案都有助于解决我提出的问题,但我觉得 OOP 方法更适合我的特定需求。从长远来看,它也更容易阅读和理解。