Jimi T
Jimi T

Reputation: 35

Foreach loop and hash table with two values:

Example 01 - below is a simplified example of code I am using in a more complicated script.This code works.

THE PROBLEM is that I want to be able to control the order in which the two sets of values - website name and URL - are processed thru the foreach loop.

I UNDERSTAND that hash-tables do not process the data in the order they are listed but rather list it out in a seemingly random fashion.

WHAT HAVE I TRIED: I've done some research on this via a book, google, and stack exchange.

I have tried using the GetEnumerator command along with its associated "sort name" option as shown in Example 02 below. This example works in this context - it successfully lists the sites according to the alphabetical order of the site name. However I do not want to list alphabetically but rather according to a stipulated order. If the ordering needs to be done manually that will be fine but I don't see how to achieve this. Furthermore, when I try to use this method with my actual script the script will run but in this section it will display " System.Collections.DictionaryEntry", rather than running the script properly. Maybe I am not running it correctly here.

WHAT ELSE HAVE I TRIED: I also tried a hash-table using two values - site name and a letter of the alphabet. This successfully listed the sites in the order I had stipulated using letters of the alphabet, BUT my actual script needs to have the two values - website name and URL - to be used in the foreach loop that governs the running of the script.

I also tried to use three values in the hash-table - thought I may have seen a note that this was possible - however if this is even possible I could not find the syntax to make this work.

FINAL THOUGHT: I was wondering if you could use two hash-tables to solve this - one to setup the order in which the foreach loop processes the values (as per Example 03 below) and the other to provide the actual values to be used in the foreach loop (as per Example 01).

Is that a possible solution or some alternative ? Is there any other way to achieve this in a reasonable fashion ?

Thanks in advance.


Example 01

 $Sites = @{
  'DuckDuckGo'    =    'https://duckduckgo.com'
  'Google'        =    'https://www.google.com'
  'Ixquick'       =    'https://www.ixquick.com'
  'Yahoo  '       =    'https://search.yahoo.com'
  'Dogpile'       =    'http://www.dogpile.com'
  'Yippee '       =    'http://www.yippy.com'
}
clear
write-host "`n`n`n"

foreach ($name in $Sites.Keys)  {
  write-host 
  "`t`t {0} `t`t`t {1}" -f $name , $Sites[$name] 
  write-host 
}

Example 02

$Sites = @{
  'DuckDuckGo'    =    'https://duckduckgo.com'
  'Google'        =    'https://www.google.com'
  'Ixquick'       =    'https://www.ixquick.com'
  'Yahoo  '       =    'https://search.yahoo.com'
  'Dogpile'       =    'http://www.dogpile.com'
  'Yippee '       =    'http://www.yippy.com'
}

clear
write-host "`n`n`n"

foreach($name in $Sites.GetEnumerator() | Sort Name)
    {
        $name 
    }

write-host "`n`n`n`n"

Example 03

$Sites = @{                                                                                             
  'DuckDuckGo'    =    'a'
  'Google'        =    'f'
  'Ixquick'       =    'c'
  'Yahoo  '       =    'z'
  'Dogpile'       =    'e'
  'Yippee '       =    'b'                                                                                                                                                                                                     
} 

$Sites.GetEnumerator() | Sort Value 

Upvotes: 0

Views: 577

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200263

You're thinking too complicated. Just sort the keys of the hashtable, like this:

$Sites.Keys | Sort-Object | ForEach-Object {
  "{0}`t{1}" -f $_, $Sites[$_]
}

or like this:

foreach ($name in ($Sites.Keys | Sort-Object)) {
  "{0}`t{1}" -f $name, $Sites[$name]
}

If you want the elements of the hashtable to be in a particular order from the start create an ordered hashtable:

$Sites = [ordered]@{
  'DuckDuckGo' = 'https://duckduckgo.com'
  'Google'     = 'https://www.google.com'
  'Ixquick'    = 'https://www.ixquick.com'
  'Yahoo  '    = 'https://search.yahoo.com'
  'Dogpile'    = 'http://www.dogpile.com'
  'Yippee '    = 'http://www.yippy.com'
}

As a side note: don't mix Write-Host and PowerShell default output (echoing of bare strings). They do different things. The latter writes to the success output stream, whereas the former writes to the host console. The order in which host and stream output are displayed may be different from what you expect.

Upvotes: 1

Related Questions