add-member массивов powershell - ищет элегантный код - PullRequest
0 голосов
/ 12 ноября 2018

У меня есть довольно простой массив PowerShell: $ TestArray с двумя текстовыми столбцами: Price и TimeStamp (так я их получаю, с этим ничего не поделаешь):

Price  TimeStamp       
-----  ----------------       
0.0567 1542056680.72746
0.0567 1542056650.34414
0.0555 1542056197.46668
0.0551 1542056167.28967

Я бы хотел, в одной строке PowerShell , чтобы добавить округленное Time2 значение

$Time2 = [math]::Round($TestArray.TimeStamp)

Код, о котором я думаю:

 $TestArray | Add-Member -Name Time2 -MemberType NoteProperty -Value { [math]::Round($Table.TimeStamp) }

Конечно, я могу сделать цикл ForEach; это легко позаботится об этом, но я бы хотел добиться этого в одной строке кода.

Есть идеи?

Ура, Philippe

Ответы [ 3 ]

0 голосов
/ 13 ноября 2018

В качестве альтернативы вы можете добиться того же с Select-Object и пользовательским свойством:

$TestArray | Select-Object *,@{ n='Time2';e={ [math]::Round($_.TimeStamp) }}
0 голосов
/ 13 ноября 2018

Ответ Матиаса Р. Джессена напрямую решает вашу проблему, создавая свойство script (тип ScriptProperty), которое динамически вычисляет его значение из вмещающегосвойство .TimeStamp объекта.

  • Преимущество этого подхода состоит в том, что даже более поздние изменения в .TimeStamp будут правильно отражаться в .Time2, хотя за счет необходимости вычислять значение для каждогоaccess.

Ответ Мануэля Батшинга предлагает альтернативу на основе Select-Object, которая создает статические свойства заметки (тип NoteProperty), так как выПервоначально пытались самостоятельно.

  • Преимущество этого подхода заключается в том, что вы несете стоимость расчета только один раз, но более поздние изменения в .TimeStamp не будут отражены в .Time2.

Чтобы предложить более быстрые альтернативы PSv5 + (каждый вызов по одному методу, разбитый по нескольким строкам для удобства чтения):

# ScriptProperty - dynamic
$TestArray.ForEach({ 
  $_.psobject.properties.Add(
    [psscriptproperty]::new('Time2', { [math]::Round($this.TimeStamp) })
  ) 
})
# NoteProperty - static
$TestArray.ForEach({ 
  $_.psobject.properties.Add(
    [psnoteproperty]::new('Time2', [math]::Round($_.TimeStamp))
  ) 
})

В вышеприведенных решениях используетсяPSv4 + .ForEach() коллекцияon метод и метод типа PSv5 + static ::new() для вызова конструкторов.


Наконец, re one-liner :

Следующий foreach -loopрешение на основе свойства примечания также решило бы вашу проблему и было бы быстрее ;в то время как он разбит на несколько строк для удобства чтения, он также работает как однострочный:

foreach ($el in $TestArray) { 
  Add-Member -InputObject $el -Name Time2 -MemberType NoteProperty `
             -Value ([math]::Round($el.TimeStamp)) 
}

Как правило, в то время как конвейер часто обеспечивает более элегантное решение с одной командой, которое, к сожалению, достигаетсяза счет производительности.

0 голосов
/ 12 ноября 2018

Измените тип элемента на ScriptProperty и обозначьте отдельный элемент массива как $this:

$TestArray |Add-Member Time2 -Value { [math]::Round($this.Timestamp) } -MemberType ScriptProperty

Стоит отметить, что в этом примере сам конвейер действует как цикл foreach, распутывая массив и привязывая каждый отдельный элемент к Add-Member

...