0

I am using hashtables in powershell for multiple entries my hastable is working fine, but for the single entry its throwing the error by not picking the value it meant to be. Suppose I am having a Line

Aman;Indore;789858585;23
Raman;Delhi;785458545;35

for this two entry, my hashtable is working fine when i am giving command for example userinput.name[0] so it will pick Aman as the value and user.input.name[1] then it picks Raman as the value.

But the same code with single entry of

Aman;Indore;789858585;23 

when I am giving userinput.name[0] so it is picking up A. The first letter of Aman it's picking instead of the complete name.

Lieven Keersmaekers
  • 57,207
  • 13
  • 112
  • 146
  • 3
    Please edit the question and include [an example](https://stackoverflow.com/help/minimal-reproducible-example) that demonstrates the problem. This sounds like a mismatch in hashtable / array access, but without code, it's just guessing. Do not add code into a comment, those are hard to read and the question should contain all the details within itself. – vonPryz Aug 11 '20 at 05:19
  • 2
    Does this answer your question? [How can I force Powershell to return an array when a call only returns one object?](https://stackoverflow.com/questions/11107428/how-can-i-force-powershell-to-return-an-array-when-a-call-only-returns-one-objec), thus: `@($userinput.name)[0]` – iRon Aug 11 '20 at 06:28
  • 1
    that does NOT look like a hashtable. it looks like a CSV text file. are you sure you are dealing with a hashtable? – Lee_Dailey Aug 11 '20 at 07:04
  • 1
    When you create it with a single line you are most likely creating it as a string and not a array of something. And as other has commented, it doesnt look like a HashTable. More like a CSV format or something similar. Please add more code and show us how you assign the variable and how you extract it. – Daniel Björk Aug 11 '20 at 08:17
  • Does this answer your question? [PowerShell: How can I to force to get a result as an Array instead of Object](https://stackoverflow.com/questions/14085077/powershell-how-can-i-to-force-to-get-a-result-as-an-array-instead-of-object) – filimonic Aug 11 '20 at 10:29

1 Answers1

1

You might not even realise it, but you're using a PowerShell feature called Member Enumeration which was introduced in PowerShell 3.0.

Basically, if you attempt to access a named property on an array, if the property doesn't exist on the array object itself then PowerShell will look for that property on all the items in the array and return those values in a new array instead.

For example:

PS> $csv = @"
Aman;Indore;789858585;23
Raman;Delhi;785458545;35
"@

PS> $data = $csv | ConvertFrom-Csv -Delimiter ";" -Header @("Name", "Location", "Mobile", "Age");

PS> $data
Name  Location Mobile    Age
----  -------- ------    ---
Aman  Indore   789858585 23
Raman Delhi    785458545 35

PS> $data.Name
Aman
Raman

# note this returns an array of objects thanks to member enumeration
PS> $data.Name.GetType().FullName
System.Object[]

PS> $data.Name[0]
Aman

In your case, $data.Name returns a new array containing the value of the Name property on all the items in $data - effectively @("Aman", "Raman"). So, when you use $data.Name[0], you're retrieving the first item in the array created by member enumeration - i.e. Aman - and all's well in the world...

Now, the catch is that if there's only one item in the array created by member enumeration it gets "unrolled" to be the value of the first item:

PS> $csv = @"
Aman;Indore;789858585;23
"@

PS> $data = $csv | ConvertFrom-Csv -Delimiter ";" -Header @("Name", "Location", "Mobile", "Age");

PS> $data
# Name  Location Mobile    Age
# ----  -------- ------    ---
# Aman  Indore   789858585 23

# note this returns a single string because the "member enumeration" array
# gets unrolled if there's only one item
PS> $data.Name.GetType().FullName
System.String

PS> $data.Name
# Aman

PS> $data.Name[0]
# A

And in your case the $data.Name[0] is equivalent to "Aman"[0] which returns A.

To fix this, rather than inadvertently use member enumeration by doing $data.Name[0], where the result can vary based on the number of items in the array, you can use one of the following:

PS> $data[0].Name
Aman

PS> @($data.Name)[0]
Aman

The first option is probably more performant in the general case, but the second is a useful workaround in some cases where the first won't work (e.g. when dealing with return values from functions / where-object, etc).

mclayton
  • 8,025
  • 2
  • 21
  • 26