如何优化从红宝石嵌套哈希中提取数据?

问题描述 投票:0回答:1

背景

我有一组嵌套的哈希,这些哈希提供了一组定义应用程序行为的参数:

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] to false, the b2b code/url pair stored in thewebsite_data`哈希将从nginx块中移除:

map $http_host $MAGE_RUN_CODE {
    luma.com base;
}

问题

上面的代码有效,但是我知道它效率极低。我对红宝石比较陌生,但我认为这很可能是逻辑上的挑战,而不是特定于语言的挑战。

我的问题是,连接这些哈希而不是像我之前那样使用循环的正确方法是什么?我已经对hash.select进行了一些阅读,看来这可能是最好的方法,但是我想知道:还有其他我应该考虑的方法可以优化此操作吗?

ruby loops hash
1个回答
0
投票

假设您有key = :foohash = { foo: 1, bar: 2 }-您想知道该键的哈希值。

您在这里使用的方法本质上是

result = nil
hsh.each { |k,v| result = v if k == :foo }

但是为什么可以这样说呢?>

result = hsh[:foo]

似乎您了解散列如何成为可迭代的结构,并且可以像数组一样遍历它们。但是您做得太过分了,而忘记了哈希是索引结构。就您的代码而言,我将这样重构:

# fixed typo here: verticlas => verticals
custom_demo_options[:verticals].each do |vertical_name, vertical_choice|
  # == true is almost always unnecessary, just use a truthiness check
  next unless vertical_choice
  custom_demo_options[:channels].each do |channel_name, channel_choice|
    next unless channel_choice
    vertical_data = website_data[:verticals][site_vertical]
    channel_value = vertical_data[channel_name]
    # This must be initialized here:
    collection = {}
    collection[:url] = channel_value[:url]
    collection[:code] = channel_value[:code]
    data.push(collection)
  end
end

您会看到许多嵌套和复杂性已被删除。请注意,我在初始化collection时添加了属性。这里要介绍的内容太多了,但我强烈建议您阅读Ruby中的可变性。您当前的代码可能无法实现预期的效果,因为您将相同的collection哈希多次推入数组中

此时,您可以将其重构为更具功能性的编程样式,并使用一些链接的方法,但是我会把这个练习留给您

© www.soinside.com 2019 - 2024. All rights reserved.