我真的很努力地嘗試不問這個問題,但我一直回到這個問題,因為我不確定我是否盡可能有效地做每件事,或者是否可能存在問題。基本上,我有一個包含數字欄位的 CSV 檔案,但它包含一個小數和十萬位的值,例如15.0000. 我需要做的就是將其轉換為沒有小數位的整數。
我在這里遇到了一個相關的問題,但所選的答案似乎對將字串表示形式直接轉換為整數資料型別產生了懷疑 - 沒有解釋原因。
簡單地將字串轉換為 an
int不會可靠地作業。您需要將其轉換為int32.
我沒有太多運氣讓[System.Convert]方法起作用,或者做類似$StringNumber.ToInt32(). 我意識到,一旦我將資料保存回PSCustomObject它們,它們將被存盤為字串,所以在一天結束時,也許我使這比我的用例所需的更復雜,我只需要重新格式化$StringNumber......但即使這樣也給我帶來了一些問題。
關于為什么在我的情況下鑄造不可靠或更好的方法來處理這個問題的任何想法?
我嘗試過的例子:
PS > $StringNumber = '15.0000'
PS > [Convert]::ToInt32($StringNumber)
#MethodInvocationException: Exception calling "ToInt32" with "1" argument(s): "Input string was not in a correct format."
PS > [Convert]::ToInt32($StringNumber, [CultureInfo]::InvariantCulture)
#MethodInvocationException: Exception calling "ToInt32" with "2" argument(s): "Input string was not in a correct format."
PS > $StringNumber.ToInt32()
#MethodException: Cannot find an overload for "ToInt32" and the argument count: "0".
PS > $StringNumber.ToInt32([CultureInfo]::InvariantCulture)
#MethodInvocationException: Exception calling "ToInt32" with "1" argument(s): "Input string was not in a correct format."
PS > $StringNumber.ToString("F0")
#MethodException: Cannot find an overload for "ToString" and the argument count: "1".
PS > $StringNumber.ToString("F0", [CultureInfo]::CurrentCulture)
#MethodException: Cannot find an overload for "ToString" and the argument count: "2".
PS > "New format: {0:F0}" -f $StringNumber
#New format: 15.0000
所以基本上我想出的是:
- 2014 年有人說將 my 轉換
string為 anint不會可靠地作業,即使似乎Cast 運算子實際上正在執行轉換 - 這些
ToInt32方法不喜歡以小數作為輸入的字串 - 顯然
String.ToString方法沒用 - 由于復合格式
String.ToString的處理順序和處理順序,我的字串表示的簡單“重新格式化”將不起作用
總結:有沒有辦法安全地將 my$StringNumber轉換為整數,如果是,那么在大型資料集上執行此操作的最有效方法是什么?
獎勵挑戰:
如果有人可以使用ForEach 魔法方法完成這項作業,那么我就請你喝啤酒。這是一些不起作用的偽代碼,但如果它起作用會很棒。據我所知,在設定 a 的值時無法參考集合中的當前專案string property
#This code DOES NOT work as written
PS > $CSVData = Import-Csv .\somedata.csv
PS > $CSVData.ForEach('StringNumberField', [int]$_.StringNumberField)
uj5u.com熱心網友回復:
如果您的字串表示可以解釋為數字,則可以將其強制轉換為整數,只要所使用的特定整數型別足夠大以容納所表示的值(例如
[int] '15.0000')的(整數部分)一個字串可以不被解釋為一個數字或表示數字,是過大(或小,對于負數),用于目標型別,導致宣告終止錯誤; 例如
[int] 'foo'或[int] '444444444444444'請注意,PowerShell 的強制轉換和隱式字串到數字的轉換使用不變文化,這意味著只有 ever
.被識別為小數點(并且,實際上被忽略,因為它被解釋為千位分組符號),與文化無關當前有效(如 所示$PSCulture)。至于您可以使用的整數型別(所有這些 - 除了開放式
[bigint]型別 - 支持::MinValue并::MaxValue確定它們可以容納的整數范圍;例如[int]::MaxValue)- 有符號整數型別:
[sbyte],[int16],[int]([int32]),[long]([int64]),[bigint] - 無符號整數型別:
[byte],[uint16],[uint]([uint32]),[ulong]([uint64]) - 但請注意 PowerShell 本身在其計算中僅使用本機有符號型別。
- 有符號整數型別:
轉換為整數型別執行半到偶數中點舍入,這意味著表示小數部分為的值的字串
.5被舍入到最接近的偶數整數;例如[int] '1.5',[int] '2.5'兩者都舍入到2。要選擇不同的中點舍入策略,請
[Math]::Round()與System.MidpointRounding引數一起使用;例如:[Math]::Round('2.5', [MidPointRounding]::AwayFromZero) # -> 3要無條件地向上或向下舍入到最接近的整數,請使用
[Math]::Ceiling()、[Math]::Floor()、 或[Math]::Truncate();例如:[Math]::Ceiling('2.5') # -> 3 [Math]::Floor('2.5') # -> 2 [Math]::Truncate('2.5') # -> 2 # [Math]::Ceiling('-2.5') # -> -2 [Math]::Floor('-2.5') # -> -3 [Math]::Truncate('-2.5') # -> -2注意:雖然結果數字在概念上是一個整數,但從技術上講,它是 a
[double]或 - 帶有顯式[decimal]或整數數字文字輸入 - a[decimal]。
至于獎金挑戰:
- 使用整數型別轉換:
[int[]] (Import-Csv .\somedata.csv).StringNumberField
注意:(Import-Csv .\somedata.csv).StringNumberField.ForEach([int])也可以,但在這里沒有優勢。
- 通過
[Math]::*()呼叫和.ForEach()陣列方法:
(Import-Csv .\somedata.csv).StringNumberField.ForEach(
{ [Math]::Round($_, [MidPointRounding]::AwayFromZero) }
)
uj5u.com熱心網友回復:
鑄造[int]為你解釋,是東西,將作業在大多數情況下,但它也容易出錯。如果數字大于[int]::MaxValue怎么辦?您可以用來避免例外的替代方法是使用-as [int]運算子,但是還有另一個問題,如果該值無法轉換為整數,您將獲得$null結果。
為了確保字串將被轉換并且您不會首先得到 null 作為結果,您需要 100% 確定您提供的資料是正確的,或者假設最壞的情況并[math]::Round(..)與-as [decimal]or-as [long]或-as [double]( ∞)結合使用四舍五入你的數字:
[math]::Round('123.123' -as [decimal]) # => 123
[math]::Round('123.asd' -as [decimal]) # => 0
注意:我正在使用 round but[math]::Ceiling(..)或[math]::Floor(..)or[math]::Truncate(..)也是有效的替代方案,具體取決于您的預期輸出。
另一種選擇是使用[decimal]::TryParse(..)但是如果有一些不是數字的東西,這會拋出:
$StringNumber = '15.0000'
$ref = 0
[decimal]::TryParse( $StringNumber, ([ref]$ref) )
[math]::Round($ref) # => 15
使用Hazrelle 的建議也可以,但同樣會因無效輸入或“值對于 Int32 而言太大或太小”而引發例外。
[System.Decimal]::ToInt32('123123123.123') # => 123123123
至于獎金挑戰,我認為不可能一次性使用 將四舍五入的值投射到您的 CSV 中ForEach(type convertToType),即使是這樣,由于之前提到的內容,它也可能帶來問題:
$csv = @'
"Col1","Col2"
"val1","15.0000"
"val2","20.123"
"val3","922337203685477.5807"
'@ | ConvertFrom-Csv
$csv.Col2.ForEach([int])
無法轉換引數“item”,值為“922337203685477.5807”,“添加”型別為“System.Int32”:“無法將值“922337203685477.5807”轉換為型別“System.Int32”。
將.foreach(..)陣列方法與腳本塊結合使用會起作用:
$csv.ForEach({
$_.Col2 = [math]::Round($_.Col2 -as [decimal])
})
如果您想知道為什么不直接使用[math]::Round(..)字串并忘記它:
[math]::Round('123.123') # => 123 Works!
但是關于:
PS /> [math]::Round([decimal]::MaxValue -as [string])
7.92281625142643E 28
PS /> [math]::Round([decimal]([decimal]::MaxValue -as [string]))
79228162514264337593543950335
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/389633.html
標籤:电源外壳
