0

I'm working in powershell with an imported CSV. I have a data set like this:

  ID            First_Name                              Last_Nam
--              ----------                              --------
2314             Kenny                                   Anderson
21588            Mark                                    Anderson
2547             Ben                                     Andrews
5797             Benjamin                                Armour

Except with 2000 people and many more columns. Currently the data is stored as a series of hashes in a @{ID = "..",First_Name:"..",Last_Name:".."} and these are stored in a System Object array. I want to store each hash as an index in an array. I want to get the hashtable at that index, but I don't know how to into the System.Object Array. Here's my code:

$csv = import-csv $csv_name 
$row = @(0)*csv.length
$hash = @{}

for($i =0; $i -lt $csv.length; $i++){
$row[$i] += $csv[$i]
}

#error: cannot convert "@{ID : "..", First_Name: "..", Last_Name:".." to Systems.Int32

for($i =0; $i -lt $csv.length; $i++){
$csv[$i].psobject.properties | Foreach { $hash[$_.Name] = $_.Value }

$row[$i]+=$hash
}

#error: Cannot convert systems.collections.hashtable into Systems.Int32

I'm looking for a way to index the array so I can get the hashtable at that index. the The first one, with pointers to the hashtables accessible through the array, is what I think would be the easiest to manipulate. If there's an easier way to get a specific hashtable just from the System.Object[] itself, please tell me.

I should add I don't know the names or amount of the columns in advance.

7
  • += is a terrible method to add to an array as it recreates and copies the entire array each time. The proper methods are 1) collecting the loop output $arr = foreach (...) { .....; $element } or 2) ArrayList. You can find more examples yourself. Commented Jan 31, 2017 at 18:46
  • @wOxxOm I see you posted this in another question too, and I don't think it's good advice. In the vast majority of cases, the performance impact on the overall task is negligible or unnoticeable. += is far more readable and clear, which is usually the more desirable trait. It's good to know the performance aspects of different ways of doing something, but to say += is terrible and improper is a stretch, in my opinion. Commented Jan 31, 2017 at 19:24
  • @briantist, collecting output from loops or pipelines is simpler, faster, more readable, more 'poshy' even in case of small arrays. Commented Jan 31, 2017 at 19:26
  • @wOxxOm it can be, depending on the use case. Advocating replacing all instances of += with a loop seems excessive to me. I respect your having an opinion on it I just feel the way you present it (+= is wrong, loop collection is right) could use some nuance. Would you say the same about string concatenation? That it should always be replaced with StringBuilder because + and += recreates a string every time? (serious question, not being rhetorical) Commented Jan 31, 2017 at 19:34
  • @briantist, the case of += with string is different: 1) it's simpler than StringBuilder while the opposite is true for the array case (with loop collection there's no need to initialize an empty array, no need to explicitly add the elements), and 2) compared to arrays strings are typically smaller/simpler, and the contents being a primitive data type is copied much faster. Commented Jan 31, 2017 at 19:47

1 Answer 1

4

The return value of Import-Csv is not an array of [hashtable]s, it's an array of [psobject]s, where each column is a property.

There's no need to build any kind of array to get an individual object by index.

$csv = import-csv $csv_name 
$csv[0]
$csv[1].First_Name
# etc

The errors in your code have nothing to do with the question you posed though; you're getting errors trying to add objects to an array, because you're actually trying to add an object or hashtable to an existing array element of type integer.

You don't need to precreate the array with a bunch of zeros, so this line isn't needed:

$row = @(0)*csv.length

Instead, you can create an empty array:

$row = @()

Then, you can just add to the array itself:

$row += $hash
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.