我一直在努力解決這個問題,并搜索了很多方法。我敢肯定,這將歸結為非常基礎。
我在 @array 中有資料,我想將其移動到 %hash 中的樹中。
這可能更適合 JSON?但我以前沒有深入研究過,也不需要保存/恢復這些資訊。
欲望:
創建一個可以相互嵌套的 USB 設備依賴樹,這些設備可以通過集線器 (deviceB) 跟蹤端點 (deviceC),最后是根 (deviceA)。
例子:
簡化(我希望......這不是來自實際較長的腳本):
我想以這種格式轉換陣列:
my @array = ['deviceA','deviceB','deviceC'];
到多維哈希等于:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } )
那會像這樣轉儲:
$VAR1 = {
'deviceA' => {
'deviceB' => {
'deviceC' => ''
}
}
};
對于僅查看單個設備,這不是必需的,但我正在構建一個包含許多設備的 IOMMU -> PCI 設備 -> USB 映射。
筆記:
- 我試圖避免安裝 CPAN 模塊,因此腳本適用于類似系統(Proxmox VE)
- 最后一個設備(上面的設備C)沒有孩子
- 值''很好
- undef 可能會作業
- 混合型別會起作用,但我需要知道如何設定
- 一旦創建,我將永遠不需要修改或操作哈希
- 我不知道遞回 @array 以填充 %hash 孩子的正確方法。* 我想要每個 USB 設備的資料水平
- 我會切換到一個物件/包,但每個設備都可以有一組不同的孩子(或沒有),這使得知道物件名稱是不可行的
- 一些 USB 設備沒有子設備(根集線器)...類似于 %hash = ('deviceA' => '')
- 有些人有 1 個孩子是最終的設備......類似于 %hash = ('deviceA' => { 'deviceB' =>'' } )
- 有些通過額外的集線器在根之間有多個步驟......類似于 %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } )或更多
初始點 :
這是基本且不完整的,但會運行:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
# data in from parsing usb device path:
my @array = ['deviceA','deviceB','deviceC'];
# needs to be converted to:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } );
print "\n\%hash:\n" . Dumper \%hash;
偽代碼
本節不是任何形式的作業代碼。我只是想記錄下我的想法。我知道格式是錯誤的,我嘗試了多種方法來創建它,而且 我看起來更愚蠢 ,展示了我所有的嘗試:)
我對裁判很陌生,我不會在這里嘗試得到它。下面的思路是:
- 對于@array 中的每個專案:
- 創建一種方式(參考或當前哈希的副本),可用于下一次迭代以放置下一個子項
- 將專案附加為具有空值的上一次迭代的子項(如果有進一步的迭代,可以附加)
my @array = ['deviceA','deviceB','deviceC'];
my %hash = {};
my %trackref;
for (@array) {
%trackref = %hash; # a copy of the existing that won't change when %hash updates
$hash{last_child} ::append_child:: $_;
}
uj5u.com熱心網友回復:
您實際上非常接近,但似乎您需要更好地理解參考。perldoc perlref可能是理解參考的一個很好的起點。
在查看解決方案之前,您的代碼中存在一些錯誤:
my @array = [ ... ];:[]創建一個arrayref,而不是一個陣列,這意味著@array實際上存盤了一個標量項:對另一個陣列的參考。用于()初始化陣列:my @array = ( ... );.my %hash = {};: 同樣,{}創建一個 hashref,而不是一個 hash。這意味著該行將單個 hashref 存盤在 中%hash,這將導致此警告:Reference found where even-sized list expected at hash.pl 行(因為散列包含鍵值并且您只提供了一個鍵)。用于()簡單(即,不是 hashref)散列。但是,在這種情況下,您不需要初始化%hash:my %hash;并my %hash = ()執行相同的操作(即創建一個空哈希)。%trackref = %hash;復制in的內容。這意味著,與名稱“trackref”所暗示的相反,它不包含對任何內容的參考,而是. 用于創建對 的參考。 請注意,如果您已經有一個 hashref,那么將它分配給另一個變數會復制該參考。例如,如果您這樣做,則兩者都參考相同的哈希。%hash%trackref%trackref%hash\%hash%hashmy $hash1 = {}; my $hash2 = $hash1$hash1$hash2
因此,在您嘗試解決這些問題時,我們得到:
my @array = ('deviceA','deviceB','deviceC');
my %hash;
my $trackref = \%hash;
for my $usb (@array) {
$trackref->{$usb} = {};
$trackref = $trackref->{$usb};
}
print Dumper \%hash;
哪個輸出:
$VAR1 = {
'deviceA' => {
'deviceB' => {
'deviceC' => {}
}
}
};
我所做的主要更改是將您$hash{last_child} ::append_child:: $_;的替換為$trackref->{$_} = {};. 但想法保持不變:將 item 作為上一次迭代的子項附加一個空值以重用您的單詞。
為了幫助您更好地理解代碼,讓我們一步一步地看看回圈中發生了什么:
在第一次迭代之前,
%hash為空且$trackref參考%hash.在第一次迭代中,我們
deviceA => {}輸入$trackref(或者,更迂腐,我們與in{}的鍵相關聯)。既然參考了,就這樣放。然后,我們存盤在我們剛剛創建的這個 new中,這意味著現在參考.deviceA$trackref$trackref%hashdeviceA => {}%hash$trackref{}$trackref$hash{deviceA}在第二次迭代中,我們
deviceB => {}輸入$trackref.$trackeref參考$hash{deviceA}(我們在上一次迭代中創建的),這意味著%hash現在是(deviceA => { deviceB => {} }). 然后我們存盤在$trackref新的{}.等等...
您會注意到,在最里面的哈希中,{}與 key 相關聯deviceC。因此,在迭代哈希時,您可以通過執行類似的操作來知道您是否在最后if (%$hash)(而不僅僅是if ($hash)最后一個{}是undefor '')。讓我知道這是否是一個問題:我們可以添加一些代碼將其轉換{}為undef(或者,您可以自己做,這將是一個很好的練習來習慣參考)
小備注:@arrayand%hash是糟糕的陣列和散列名稱,因為@已經表示一個陣列,并且%已經表示一個散列。您可能只是將這些名稱用于您的問題的這個小示例,在這種情況下,沒問題。但是,如果您在實際代碼中使用這些名稱,請考慮將它們更改為更明確的內容......@usb_devices也許%usb_devices_tree?
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/466454.html
