簡體   English   中英

使用數組值作為散列鍵在 Ruby 中創建嵌套散列

[英]Using array values as hash keys to create nested hashes in Ruby

背景

我有一個文件目錄。 其中大部分是.patch文件,盡管其中一些不是。 對於每個補丁文件,我需要掃描始終是字符串的第一行並提取該行的一部分。 結合每個文件的名稱、每個第一行的那部分以及每個文件的唯一標識符,我需要創建一個哈希,然后將其轉換為 json 並寫入文件。

以下是示例:

文件目錄(示例)

|__ .gitkeep
|__ pmet-add-install-module-timings.patch
|__ pmet-change-sample-data-load-order.patch
|__ pmet-stop-catching-sample-data-errrors-during-install.patch
|__ pmet-fix-admin-label-word-breaking.patch
|__ pmet-declare-shipping-factory-for-compilation.patch.disabled

...

第一行示例

文件名: pmet-add-install-module-timings.patch

第一行: diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php

文件名: pmet-change-sample-data-load-order.patch

第一行: diff --git a/vendor/magento/module-sample-data/etc/module.xml b/vendor/magento/module-sample-data/etc/module.xml

文件名: pmet-stop-catching-sample-data-errrors-during-install.patch

第一行: diff --git a/vendor/magento/framework/Setup/SampleData/Executor.php b/vendor/magento/framework/Setup/SampleData/Executor.php

文件名: pmet-fix-admin-label-word-breaking.patch

第一行: diff --git a/vendor/magento/theme-adminhtml-backend/web/css/styles-old.less b/vendor/magento/theme-adminhtml-backend/web/css/styles-old.less

JSON 文件示例

{
    "patches": {
        "magento/magento2-base": {
            "Patch 1": "m2-hotfixes/pmet-add-install-module-timings.patch"
        },
        "magento/module-sample-data": {
            "Patch 2": "m2-hotfixes/pmet-change-sample-data-load-order.patch"
        },
        "magento/theme-adminhtml-backend": {
            "Patch 3": "m2-hotfixes/pmet-fix-admin-label-word-breaking.patch"
        },
        "magento/framework": {
            "Patch 4": "m2-hotfixes/pmet-stop-catching-sample-data-errrors-during-install.patch"
        }
    }
}

到目前為止的解決方案scrape.rb

這是完整的代碼。 我將在下面進一步分解:

files_hash = Hash.new
modules = Array.new
data_hash = {
    patches: {}
}
files = Dir["*.patch"]
files.each do |file|
    files_hash.store(files.index(file), file)
end
files_hash.each do |key, file|
    value = File.open(file, &:readline).split('/')[3]
    if value.match(/module-/) || value.match(/theme-/)
        result = "magento/#{value}"
    else
        result = "magento2-base"
    end
    modules << result
    modules.each do |val|
        data_hash[:patches][val][key] = "m2-hotfixes/#{file}"
    end
end
print data_hash

在我強調這個問題之前,我需要首先詳細說明我為達到預期的最終結果所做的工作:

首先,我設置了一個空文件哈希、模塊數組和數據哈希:

files_hash = Hash.new
modules = Array.new
data_hash = {
    patches: {}
}

接下來,我掃描補丁文件目錄中的.patch文件,並將它們與它們的密鑰一起存儲在文件散列中。 (我想我可以使用密鑰作為 JSON 文件中的補丁標簽):

files = Dir["*.patch"]
files.each do |file|
    files_hash.store(files.index(file), file)
end

接下來,我使用文件哈希讀取每個補丁文件的第一行。 我注意到補丁文件中有一個我認為可靠的模式:每個文件都有magento/module-namemagento/theme-name或其他東西。 module-nametheme-name案例都將使用magento/#{value}語法。 “其他”案例將使用magento/magento2-base

files_hash.each do |key, file|
    value = File.open(file, &:readline).split('/')[3]
    if value.match(/module-/) || value.match(/theme-/)
        result = "magento/#{value}"
    else
        result = "magento2-base"
    end
    modules << result
...

這不是最理想的解決方案(如果 diff 結構發生變化怎么辦?)但它現在有效,我無法弄清楚用於搜索字符串並返回相同結果的正確正則表達式。 上面的代碼給了我我想要的,這是以下數組:

#=>["magento2-base", "magento/module-sample-data", "magento/theme-adminhtml-backend", "magento2-base"]

接下來,雖然仍然能夠從文件哈希中訪問文件名和鍵,但我需要遍歷這個數組並創建以數組值作為鍵和文件名作為值(附加到文件路徑)的哈希。 像這樣,(或者我是這么認為的):

    modules.each do |val|
        data_hash[:patches][val][key] = "m2-hotfixes/#{file}"
    end
end

這是我遇到問題的代碼的這一部分。 運行這會給我以下錯誤:

Traceback (most recent call last):
    4: from scrape.rb:10:in `<main>'
    3: from scrape.rb:10:in `each'
    2: from scrape.rb:18:in `block in <main>'
    1: from scrape.rb:18:in `each'
scrape.rb:19:in `block (2 levels) in <main>': undefined method `[]=' for nil:NilClass (NoMethodError)

我注意到,如果我像這樣省略keydata_hashdata_hash[:patches][val] ,我會得到一個值的散列。

那么,我顯而易見的問題是:

為什么我使用上面的鍵將哈希進一步嵌套一層的方法不起作用?

這是我想出的答案:

require 'json'

files_hash = Hash.new
file_hash = Hash.new
result_hash = Hash.new
data_hash = Hash.new
remap_hash = Hash.new 
final_hash = {"patches" => {}}
files = Dir["*.patch"]
patches_file = File.dirname(File.expand_path(__FILE__)) + "/patches.json"

files.each do |file|
    files_hash.store(files.index(file), file)
end
files_hash.each do |key, file|
    value = File.open(file, &:readline).split('/')[3]
    if value.match(/module-/) || value.match(/theme-/)
        result = "magento/#{value}"
    else
        result = "magento2-base"
    end
    data_hash[key] = result
    file_hash[key] = "m2-hotfixes/#{file}"
end

data_hash.each do |data_key, data_vals|
    file_hash.each do |file_key, file_vals|
        if data_key == file_key
            remap_hash[data_vals] = {
                "Patch #{data_key}" => file_vals
            }
        end
    end
end

final_hash["patches"].merge!(remap_hash)

File.open(patches_file, "w+") do |file|
    file.puts(final_hash.to_json)
end

這會產生以下結果: patches.json注意:我使用了與上面不同的補丁文件集,關鍵是這里的格式:

{
    "patches": {
        "magento2-base": {
            "Patch 6": "m2-hotfixes/pmet-fix-module-loader-algorithm.patch"
        },
        "magento/module-downloadable-sample-data": {
            "Patch 2": "m2-hotfixes/pmet-fix-sample-data-code-generator.patch"
        },
        "magento/module-customer": {
            "Patch 3": "m2-hotfixes/pmet-visitor-segment.patch"
        }
    }
}

一些優點和缺點:

優點

有用。 驚人的。

缺點

  1. 我知道它可以更優雅

  2. 我遇到的一個不可預見的需求是我的patches.json文件可能有重復的補丁,需要應用到同一個文件。 就像是:

{
    "patches": {
        "magento2-base": {
            "Patch 1": "m2-hotfixes/pmet-add-install-module-timings.patch"
            "Patch 6": "m2-hotfixes/pmet-fix-module-loader-algorithm.patch"
        },
        "magento/module-downloadable-sample-data": {
            "Patch 2": "m2-hotfixes/pmet-fix-sample-data-code-generator.patch"
        },
        "magento/module-customer": {
            "Patch 3": "m2-hotfixes/pmet-visitor-segment.patch"
        }
    }
}

我的解決方案需要考慮到這一點,因為 Ruby 不允許散列中有重復的鍵。

對於考慮到這種怪癖的挑戰,我歡迎一個更優雅的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM