背景
在 PowerShell 中構建哈希表以通過特定屬性快速訪問物件是很常見的,例如基于以下內容的索引LastName:
$List = ConvertFrom-Csv @'
Id, LastName, FirstName, Country
1, Aerts, Ronald, Belgium
2, Berg, Ashly, Germany
3, Cook, James, England
4, Duval, Frank, France
5, Lyberg, Ash, England
6, Fischer, Adam, Germany
'@
$Index = @{}
$List |ForEach-Object { $Index[$_.LastName] = $_ }
$Index.Cook
Id LastName FirstName Country
-- -------- --------- -------
3 Cook James England
在某些情況下,需要在兩個(甚至更多)屬性上構建索引,例如 theFirstName和 the LastName。為此,您可以創建一個多維鍵,例如:
$Index = @{}
$List |ForEach-Object {
$Index[$_.FirstName] = @{}
$Index[$_.FirstName][$_.LastName] = $_
}
$Index.James.Cook
Id LastName FirstName Country
-- -------- --------- -------
3 Cook James England
但是將這兩個屬性連接起來更容易(甚至可能更快)。如果僅用于檢查條目是否存在:如果不存在$Index.ContainsKey('James').ContainsKey('Cook')可能會發生錯誤。
要連接屬性,需要在屬性之間使用分隔符,否則不同的屬性串列可能最終成為相同的鍵。作為這個例子:和。FirstNameAshlyBergAshLyberg
$Index = @{}
$List |ForEach-Object { $Index["$($_.FirstName)`t$($_.LastName)"] = $_ }
$Index."James`tCook"
Id LastName FirstName Country
-- -------- --------- -------
3 Cook James England
注意:以上是最小的、可重現的示例。在現實生活中,我多次提出以下問題,其中包括一般連接物件,其中背景和索引中使用的屬性數量是可變的。
問題:
- 在這種情況下加入(連接)屬性是一種好習慣嗎?
- 如果是,是否有(標準?)分隔符?(意味著一個字符 - 或一系列字符 - 不應該在屬性名稱中使用/存在)
uj5u.com熱心網友回復:
我建議不要加入密鑰,而是在Tuple班級的幫助下使用“拆分密鑰”。在這種情況下,不需要分隔符,因為鍵沒有連接,而是作為單獨的屬性存盤在物件中。該類提供了必要的介面,因此當在任何(例如)Tuple中使用時,元組就像單個鍵一樣。DictionaryHashtable
$List = ConvertFrom-Csv @'
Id, LastName, FirstName, Country
1, Aerts, Ronald, Belgium
2, Berg, Ashly, Germany
3, Cook, James, England
4, Duval, Frank, France
5, Lyberg, Ash, England
6, Fischer, Adam, Germany
'@
$Index = @{}
$List.ForEach{ $Index[ [Tuple]::Create( $_.LastName, $_.FirstName ) ] = $_ }
$Index
當寫入控制臺時,拆分鍵的格式會很好:
Name Value
---- -----
(Berg, Ashly) @{Id=2; LastName=Berg; FirstName=Ashly; Country=Germany}
(Lyberg, Ash) @{Id=5; LastName=Lyberg; FirstName=Ash; Country=England}
(Duval, Frank) @{Id=4; LastName=Duval; FirstName=Frank; Country=France}
(Aerts, Ronald) @{Id=1; LastName=Aerts; FirstName=Ronald; Country=Belgium}
(Cook, James) @{Id=3; LastName=Cook; FirstName=James; Country=England}
(Fischer, Adam) @{Id=6; LastName=Fischer; FirstName=Adam; Country=Germany}
要查找條目,請創建一個臨時元組:
$Index[ [Tuple]::Create('Duval','Frank') ]
該類的一個優點Tuple是您可以輕松獲取組成拆分鍵的各個鍵,而無需拆分字串:
# Using member access enumeration
$Index.Keys.Item1 # Prints all last names
$Index.Keys.Item2 # Prints all first names
# Using the enumerator to loop over the index
$Index.GetEnumerator().ForEach{ $_.Key.Item1 }
.NET Framework 4.7 添加了結構(有什么區別?)。可能值得測驗它是否為這個用例提供了更好的性能。此外,用泛型替換也可以提高性能:ValueTuple HashtableDictionary
$Index = [Collections.Generic.Dictionary[ ValueTuple[String,String], object]]::new()
除了字典的構造,ValueTuple還可以像Tuple. 只需在前面的代碼示例中替換Tuple為。ValueTuple
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/496654.html
