Как не допустить, чтобы командлет Measure-Object PowerShell урезал ваши данные? - PullRequest
3 голосов
/ 09 марта 2020

Я пытаюсь сравнить следующие данные, чтобы получить наибольшее число:

$UserDeets 

name                 lastLogon
----                 ---------
Frank Ti 132273694413991065
Frank Ti 132279742884182029
Frank Ti 132282196073500496
Frank Ti 132272912975826719
Frank Ti 132282144707771693
Frank Ti 132228790551703041

Для этого я пытаюсь использовать встроенную функцию измерения. Это код, который я исполняю выкл.

Есть ли способ предотвратить это усечение?

Ответы [ 4 ]

1 голос
/ 10 марта 2020

Джероен Мостерт предоставил важные указатели в комментарии к вопросу:

К сожалению, начиная с PowerShell 7.0, Measure-Object неизменно преобразует входные данные числа [1] для операций -Sum, -Maximum, -Minimum, -Average и -StandardDeviation до [double] (System.Double) и сообщает результат как этот тип, который может привести к потере точности.

Ваши входные числа имеют тип [long], и их значения превышают максимальное целое число, которое может быть точно представлено в [double], то есть 9007199254740991 (вы можете вычислить его с помощью [bigint]::pow(2, 53) - 1)

Эффективным обходным путем является использование LINQ (System.Linq.Enumerable.Max):

[Linq.Enumerable]::Max(
  [long[]] $UserDeets.lastLogon
)

Обратите внимание, что явное [long[]] приведение необходимо для того, чтобы PowerShell мог вызывать метод generi c .Max() с конкретным типом.

Другой, менее эффективный, но больше PowerShell-idiomati c обходной путь должен использовать сортировку , аналогично собственному ответу OP :

# Sort the LastLogon property values, then grab the *last* one,
# which is the largest value.
($UserDeets.LastLogon | Sort-Object)[-1]

сортировка только массива .lastLogon значений, а не полные входные объекты сводит к минимуму ненужные в концептуальном отношении затраты на создание дублированного, отсортированного массива просто так, макс. значение может быть определено.


[1] Обратите внимание, что для -Min и -Max non-numberri c входы также принимаются, пока они реализуют интерфейс System.IComparable, и в этом случае входные данные сохраняются как есть и не происходит потери точности; например, 'c', 'b', 'a' | Measure-Object -Minimum и [datetime]::now, [datetime]::now.AddDays(1) | Measure-Object -Maximum работают нормально, потому что оба типа [string] и [datetime] реализуют IComparable.

0 голосов
/ 09 марта 2020

Я думаю, вы пытаетесь получить последний вход для пользователей, проверив несколько D C, я делаю это с помощью этого кода (где: $samacc - текущий пользователь, $controller -списки всех D C имен хостов.) :

$scriptblock={
    param($samacc,$controller)
    $result=@()
    foreach($cont in $controller){
    $RESULT=$result + (Get-ADUser -Server $cont -Identity $samacc -Properties lastlogon,whenchanged,displayname,title,company  | sort-object lastLogon -descending | select-object enabled,displayname,samaccountname,title,company, @{Name="lastLogon";Expression={[datetime]::FromFileTime($_.'lastLogon')}},whenchanged)
    }
    $result|Sort-Object -Descending -Property LastLogon|select -First 1
    }
0 голосов
/ 09 марта 2020

Это сработало для меня. Верните его из 64-разрядного числа с плавающей запятой в 64-разрядное целое число. Но некоторые числа будут немного не соответствовать (ошибка .000000000000005 или 5/1 квадриллион%), или 6 десятых миллионных долей секунды (тики), если это было время даты.

$jsontext = @'
[ { name: 'Frank Ti', lastLogon: 132273694413991065 },
  { name: 'Frank Ti', lastLogon: 132279742884182029 },
  { name: 'Frank Ti', lastLogon: 132282196073500496 },
  { name: 'Frank Ti', lastLogon: 132272912975826719 },
  { name: 'Frank Ti', lastLogon: 132282144707771693 },
  { name: 'Frank Ti', lastLogon: 132228790551703041 },
  { name: 'Frank Ti', lastLogon: 132282196073500499 },
  { name: 'Frank Ti', lastLogon:   9007199254740991 } ]
'@

$userdeets = $jsontext | convertfrom-json
[long]($userdeets | measure lastlogon -Maximum).maximum

132282196073500496
0 голосов
/ 09 марта 2020

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

Сначала я отсортировал массив:

$UserDeets = ($UserDeets | Sort-Object -Property LastLogon)

самый высокий объект будет в конце массива и может быть получен как это:

$UserDeets[-1]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...