Customization of PowerShell hash table merges

by Klaus Graefensteiner 8/12/2008 4:36:30 AM

Introduction

PowerShell provides the += operator to add one hash table to another hash table. By default this operation will result in an error, if both hash tables have at least one key that is common in both collections. In some cases you may want to have a more granular control. For example, you don't want to get an error, if not only the key, but also the value is common in both collections. On top of this somebody might want to allow an overwrite, if the key and the value are going to be identical as result of the merge. This could be useful, if the hash table is used as template for replacing strings. Updating the master table by adding a key value pair that refers to the same string would mean to exclude this particular replacement pair from the replacement transactions.

Key Value Pairs

Figure 1: Key Value Pairs

Default operator+= implementation

   1: $target = @{}
   2: $source = @{}
   3:  
   4: $target.a = "aaaaa"
   5: $target.b = "bbbbb"
   6: $target.c = "ccccc"
   7: $target.d = "ddddd"
   8:  
   9: $source.a = "aa"
  10: $source.b = "bb"
  11: $source.c = "ccccc"
  12: $source.d = "dd"
  13: $source.e = "ee"
  14: $source.f = "ff"
  15:  
  16: #------------------------- Standard Merge ----------------------------
  17:  
  18: # Keys a, b, c, d are both in hash tables $source and $target. The merge will fail
  19: $target += $source
  20:  
  21: #OUTPUT
  22: #The '+=' operator failed: Item has already been added. Key in dictionary: 'a'  Key being added: 'a'.
  23: #At line 21, position 11
  24: #$target += $source

Customized merge implementation

Duplicate pairs allowed

   1: #------------------------- Manual Merge no ambiguity ------------------
   2:  
   3: $target = @{}
   4: $source = @{}
   5:  
   6: $target.a = "aaaaa"
   7: $target.b = "bbbbb"
   8: $target.c = "ccccc"
   9: $target.d = "ddddd"
  10:  
  11: $source.a = "aaaaa"
  12: $source.b = "bbbbb"
  13: $source.c = "ccccc"
  14: $source.d = "ddddd"
  15: $source.e = "ee"
  16: $source.f = "ff"
  17:  
  18: # Allows merges if identical value-key pairs are in $source and $target in this example they 
  19: # a = "aaaaa"
  20: # b = "bbbbb"
  21: # c = "ccccc"
  22: # d = "ddddd"
  23:  
  24: $Source.GetEnumerator() | ForEach-Object                                                 `
  25: {                                                                                     `
  26:     if(!$Target.ContainsKey($_.key))                                                                        
  27:     {                                                                            `
  28:         "`$Source does not contain Key $($_.Key)"; $Target[$_.key] = $_.value                 `
  29:     }                                                                             `
  30:     else                                                                             `
  31:     {                                                                                 `
  32:         if($Target[$_.key] -ne $Source[$_.key])                                        `
  33:         {                                                                             `
  34:             throw "FATAL ERROR while merging tables! REASON: Ambigous key-value mapping! $($_.Key)=$($Target[$_.key]) and $($_.Key)=$($Source[$_.key])"  `
  35:         }                                                                                    `
  36:     }                                                                                        `
  37: }    
  38:  
  39: $target
  40:  
  41: #OUTPUT
  42: #$Source does not contain Key f
  43: #$Source does not contain Key e
  44: #
  45: #Name                           Value                                               
  46: #----                           -----                                               
  47: #e                              ee                                                  
  48: #a                              aaaaa                                               
  49: #f                              ff                                                  
  50: #b                              bbbbb                                               
  51: #d                              ddddd                                               
  52: #c                              ccccc 

Ambiguous pairs cause error

   1: #------------------------- Manual merge with ambiguity --------------------------
   2:  
   3: $target = @{}
   4: $source = @{}
   5:  
   6: $target.a = "aa"
   7: $target.b = "bb"
   8: $target.c = "ccccc"
   9: $target.d = "ddddd"
  10:  
  11: $source.a = "aaaaa"
  12: $source.b = "bbbbb"
  13: $source.c = "ccccc"
  14: $source.d = "ddddd"
  15: $source.e = "ee"
  16: $source.f = "ff"
  17:  
  18: # Fails if merge encounters ambiguity, a="aa" and a="aaaaa" also b="bb" and b="bbbbb"
  19:  
  20: $Source.GetEnumerator() | ForEach-Object                                                 `
  21: {                                                                                     `
  22:     if(!$Target.ContainsKey($_.key))                                                                        
  23:     {                                                                            `
  24:         "`$Source does not contain Key $($_.Key)"; $Target[$_.key] = $_.value                 `
  25:     }                                                                             `
  26:     else                                                                             `
  27:     {                                                                                 `
  28:         if($Target[$_.key] -ne $Source[$_.key])                                        `
  29:         {                                                                             `
  30:             throw "FATAL ERROR while merging tables! REASON: Ambigous key-value mapping! $($_.Key)=$($Target[$_.key]) and $($_.Key)=$($Source[$_.key])"  `
  31:         }                                                                                    `
  32:     }                                                                                        `
  33: }    
  34:  
  35: $target    
  36:  
  37: #OUTPUT
  38: #FATAL ERROR while merging tables! REASON: Ambigous key-value mapping! a=aa and a=aaaaa
  39: #At line 19, position 98

Download

The PowerShell script can be downloaded here: MergeStudy.zip

Ausblick

Now that I have a custom solution for merging hash tables, I would like to use this to override the default behavior of the += operator of the hash table object. I think it should be possible using the one of the member extension objects used by PSObject. Ideally I would like to have this behavior be specialized based on the key and value data types. Next I am gong to research the operator overriding  and specialization in generics in PowerShell and .NET.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

PowerShell

Related posts

Comments are closed

Powered by BlogEngine.NET 1.3.0.0
Vanilla Theme by Klaus Graefensteiner

About Klaus Graefensteiner

GRAVATAR icon of Klaus Graefensteiner I enjoy the programming of machines.

E-mail me Send mail
Blogroll as OPML OPML LinkedIn Profile View Klaus Graefensteiner's LinkedIn profile

Calendar

<<  November 2008  >>
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Sign in