HOWTO · PowerShell

如何在 PowerShell 中建立陣列、雜湊表和字典

透過本綜合指南學習如何在 PowerShell 中建立和使用陣列、雜湊表和有序字典。了解主要區別、如何存取、新增和刪除項,以及何時使用每種資料結構。包括實用範例、真實用例和常見問題部分,幫助你高效掌握 PowerShell 腳本和資料操作。無論是初學者還是希望提高 PowerShell 自動化和資料組織能力的進階使用者,都非常適合。

本頁內容

對於一系列值,選擇陣列(@());對於鍵值查找,選擇雜湊表(@{});當必須保留鍵被加入的順序時,選擇有序字典([ordered]@{})。下面的範例是自包含的 PowerShell 片段。這些範例沒有可用的執行時觀察,因此不主張任何輸出。

在 PowerShell 中建立陣列

陣列在一個變數中儲存多個值。PowerShell 陣列的索引從零開始,-1 指最後一個元素。@() 明確地將結果收集為陣列,包括當命令傳回單個值時。執行此範例:

$items = @('apple', 'banana', 'cherry')
$items[0]
$items[-1]
$items += 'date'
$items = @($items | Where-Object { $_ -ne 'banana' })
$items -join ', '

該範例讀取第一個和最後一個值,附加一個值,然後賦值一個排除了 banana 的過濾後陣列。PowerShell 陣列大小固定;+= 會建立一個結果陣列並將其賦值回去,因此反覆向大陣列附加可能需要反覆複製。對於頻繁的新增和刪除,可變集合如 System.Collections.Generic.List[object] 可能更合適。要檢查陣列的型別,請使用 $items.GetType().FullName;對於這些字串值,@() 產生的是 Object[]。

在 PowerShell 中使用雜湊表

PowerShell 雜湊表將鍵對應到值。用 @{} 建立一個,用括號表示法讀取一個項,賦值一個鍵以新增或取代一個項,並呼叫 .Remove() 刪除一個項。括號對任意鍵名都能可靠地工作;當鍵是一個簡單的類似屬性的名稱時,點表示法很方便,但可能與 Count 等內建成員衝突。

$inventory = @{ Fruit = 'Apple'; Color = 'Red'; Count = 5 }
$inventory['Color']
$inventory['Shape'] = 'Round'
$inventory.Remove('Color')
$inventory.GetEnumerator() | Sort-Object Name | ForEach-Object {
    "{0}={1}" -f $_.Name, $_.Value
}

最後一個管道將輸出的項按鍵排序以便顯示。它不會對原始雜湊表進行重新排序或取代。PowerShell 的雜湊表鍵預設不區分大小寫;當鍵的比較語義需要不同的時候,請使用其他集合。

在 PowerShell 中建立有序字典

[ordered] 字面值會建立一個有序字典,並保留項被插入的順序。像在雜湊表中一樣,使用鍵存取和更新項。插入順序不同於字母排序:除非你明確地對一個單獨的結果進行排序,否則原始順序仍然是插入序列。

$settings = [ordered]@{ Name = 'Delft'; Region = 'South Holland'; Active = $true }
$settings['Region']
$settings['Timezone'] = 'Europe/Amsterdam'
$settings.GetEnumerator() | ForEach-Object {
    "{0}={1}" -f $_.Key, $_.Value
}

雜湊表與有序字典:主要區別

| 特徵 | 雜湊表 | 有序字典 |
| PowerShell 字面值 | @{} | [ordered]@{} |
| 資料模型 | 鍵對應到值 | 鍵對應到值 |
| 迭代順序 | 不要依賴插入順序 | 保留插入順序 |
| 讀取或更新一個項 | $table['key'] | $dictionary['key'] |
| 最適合 | 當顯示順序不重要時按鍵查找 | 插入順序很重要的鍵值資料 |

PowerShell 雜湊表並不等同於每一種 .NET 字典型別。System.Collections.Hashtable 是 PowerShell 的 @{} 字面值所使用的 .NET 型別,而 .NET 還提供了其他具有各自排序和比較行為的字典實作。請根據你的程式碼所需的具體型別和行為進行選擇。不要在沒有測量實際工作負載的情況下就斷定任一集合更快。

實際用例

當輸出應遵循所選順序時,對使用者或設定欄位使用有序字典。使用雜湊表按鍵對單詞進行計數。這些範例展示了這兩項任務;程式碼是獨立的,不主張任何輸出。

$user = [ordered]@{
    Name = 'John Doe'
    Email = 'johndoe@example.com'
    Role = 'Admin'
}
$user.GetEnumerator() | ForEach-Object { "{0}: {1}" -f $_.Key, $_.Value }

$text = 'apple banana apple orange apple banana'
$wordCount = @{}
$text.Split() | ForEach-Object {
    if ($wordCount.ContainsKey($_)) {
        $wordCount[$_] += 1
    } else {
        $wordCount[$_] = 1
    }
}
$wordCount.GetEnumerator() | Sort-Object Name | ForEach-Object {
    "{0}: {1}" -f $_.Name, $_.Value
}

結論

對於按位置處理的有序序列,使用陣列;對於基於鍵的查找,使用雜湊表;當插入序列本身就是你所呈現資料的一部分時,使用有序字典。請記住,陣列的 += 會賦值一個新陣列,過濾會傳回一個需要賦值的結果,而對雜湊表列舉出的項進行排序改變的是顯示的結果,而不是表本身。

常見問題(FAQ)

PowerShell 中雜湊表和字典有什麼區別?

在日常的 PowerShell 使用中,「字典」可以描述一種通用的鍵值結構,而 @{} 會建立一個以 .NET 的 System.Collections.Hashtable 型別為基礎的 PowerShell 雜湊表。.NET 類別庫也有不同的字典型別,因此當 API 需要特定的實作時,請檢查具體的型別。

如何向 PowerShell 陣列新增或從中刪除項?

用 $array += 'newItem' 附加,然後將結果賦值回變數。要刪除相符的值,請進行過濾並賦值結果,例如 $array = @($array | Where-Object { $_ -ne 'itemToRemove' })。這些操作產生的結果是一個陣列;它們不會就地調整現有陣列的大小。

我可以在 PowerShell 中對雜湊表進行排序嗎?

使用 $hash.GetEnumerator() | Sort-Object Name 對其項進行排序以便顯示。這會傳回排序後的項,並保持 $hash 不變。當你需要插入順序時,請使用 [ordered]@{};它保留項被加入的順序,而不是按字母順序對鍵進行排序。