PowerShell:在哈希表值集合中排序

PowerShell:在哈希表值集合中排序,powershell,hashtable,sort-object,Powershell,Hashtable,Sort Object,我有一个测试输入csv文件,如下所示: ID;Product;Price;Discount;Level 1;Alpha;23.00;0.03;A 2;Bravo;17.00;0.01;A 3;Charlie;11.00;0.05;A 4;Delta;17.00;0.05;A 5;Echo;29.00;0.07;A 6;Foxtrot;11.00;0.01;A 7;Golf;11.00;0.01;A 1;Hotel;53.00;0.11;B 2;India;53.00;0.13;B 3;Julie

我有一个测试输入csv文件,如下所示:

ID;Product;Price;Discount;Level
1;Alpha;23.00;0.03;A
2;Bravo;17.00;0.01;A
3;Charlie;11.00;0.05;A
4;Delta;17.00;0.05;A
5;Echo;29.00;0.07;A
6;Foxtrot;11.00;0.01;A
7;Golf;11.00;0.01;A
1;Hotel;53.00;0.11;B
2;India;53.00;0.13;B
3;Juliet;61.00;0.11;B
1;Kilo;79.00;0.23;C
2;Lima;89.00;0.23;C
3;Mike;97.00;0.29;C
4;November;83.00;0.17;C
5;Oscar;79.00;0.11;C
我想生成以下输出文件:

ID;Product;Price;Discount;Level
1;Alpha;23.00;0.03;A
5;Echo;29.00;0.07;A
2;India;53.00;0.13;B
3;Juliet;61.00;0.11;B
2;Lima;89.00;0.23;C
3;Mike;97.00;0.29;C
也就是说,对于每个级别,我希望选择按价格排序的前两行,然后选择折扣。例如,对于级别
B
,我想要
Juliet
India
而不是
Juliet
Hotel

我有下面的代码片段,它不能完全交付

$input = '.\TestInput.csv'
$products = @(Import-CSV -Path $input -Delimiter ";")
$levels = $products | 
    Group-Object -Property Level -AsHashTable 

$sales = $levels.GetEnumerator() | 
    Sort-Object -Property @{ Expression = { [int]($_.Price) } ; Descending = $true },
                          @{ Expression = { [int]($_.Discount) } ; Descending = $true } | 
    Select-Object -first 2

$output = '.\TestOutput.csv'
$sales | Export-Csv -Path $output -Delimiter ";" -NoTypeInformation

我缺少什么?

直接在
导入Csv
输出上使用
组对象

$sales = ForEach ($Level in $levels.Keys | Sort-Object) { $levels.$Level | Sort-Object -Property  price,discount | Select-Object -last 2 }
Import-Csv '.\TestInput.csv' -Delimiter ';' | 
  Group-Object Level | 
    ForEach-Object { 
      $_.Group |
        Sort-Object { [int] $_.Price }, { [int] $_.Discount } |
          Select-Object -Last 2
    } | 
        Export-Csv -Path '.\TestOutput.csv' -Delimiter ";" -NoTypeInformation

注意:在PowerShell[Core]v6+中,您可以用
-Bottom 2
替换
| Select Object Last 2
,因为
排序对象
现在支持
-Top
-Bottom
参数


至于你所尝试的:

  • 虽然
    组对象
    通常按照指定的分组标准(在本例中为
    级别
    )对结果组进行排序,但如果使用
    -AsHashtable
    ,则由于哈希表项本身是无序的,因此不再保证这种排序

    • 为了防止出现这种情况,可以使用默认输出(no
      -AsHashtable
      )——生成单个组对象——如上所示,或者添加一个按
      级别进行排序的最终
      排序对象
      调用
  • $levels.GetEnumerator()
    通过管道发送键值对(
    System.Collections.DictionaryEntry
    实例),其
    .key
    属性是分组标准(
    .Level
    ),其
    .value
    属性是关联的组

    • 但是,您应该只通过管道发送输入值,即组对象,而不是键值对;这可以通过访问哈希表的
      .Values
      属性来实现
      • 但是,由于您需要单独处理每个组,为了找到每个组中的最大值,您需要一个中间的
        ForEach对象
        调用,在该调用中执行特定于组的处理
  • 您正在使用基于哈希表的动态属性定义来指定排序对象的标准;但是,使用
    排序对象
    ,这是不必要的,因为您永远不会看到这样一个属性的名称;因此,直接使用上面的表达式脚本块(如图所示)就足够了

  • 由于排序是按降序进行的,
    Select Object-First 2
    将按降序显示两个最高的值,而所需的输出则按升序进行请求

    • 要获得后者,请按升序排序,然后选择最后两个对象
总而言之(但请注意,顶部的解决方案在概念上更简单,效率也更高):


直接在
导入Csv
输出上使用
组对象

Import-Csv '.\TestInput.csv' -Delimiter ';' | 
  Group-Object Level | 
    ForEach-Object { 
      $_.Group |
        Sort-Object { [int] $_.Price }, { [int] $_.Discount } |
          Select-Object -Last 2
    } | 
        Export-Csv -Path '.\TestOutput.csv' -Delimiter ";" -NoTypeInformation

注意:在PowerShell[Core]v6+中,您可以用
-Bottom 2
替换
| Select Object Last 2
,因为
排序对象
现在支持
-Top
-Bottom
参数


至于你所尝试的:

  • 虽然
    组对象
    通常按照指定的分组标准(在本例中为
    级别
    )对结果组进行排序,但如果使用
    -AsHashtable
    ,则由于哈希表项本身是无序的,因此不再保证这种排序

    • 为了防止出现这种情况,可以使用默认输出(no
      -AsHashtable
      )——生成单个组对象——如上所示,或者添加一个按
      级别进行排序的最终
      排序对象
      调用
  • $levels.GetEnumerator()
    通过管道发送键值对(
    System.Collections.DictionaryEntry
    实例),其
    .key
    属性是分组标准(
    .Level
    ),其
    .value
    属性是关联的组

    • 但是,您应该只通过管道发送输入值,即组对象,而不是键值对;这可以通过访问哈希表的
      .Values
      属性来实现
      • 但是,由于您需要单独处理每个组,为了找到每个组中的最大值,您需要一个中间的
        ForEach对象
        调用,在该调用中执行特定于组的处理
  • 您正在使用基于哈希表的动态属性定义来指定排序对象的标准;但是,使用
    排序对象
    ,这是不必要的,因为您永远不会看到这样一个属性的名称;因此,直接使用上面的表达式脚本块(如图所示)就足够了

  • 由于排序是按降序进行的,
    Select Object-First 2
    将按降序显示两个最高的值,而所需的输出则按升序进行请求

    • 要获得后者,请按升序排序,然后选择最后两个对象
总而言之(但请注意,顶部的解决方案在概念上更简单,效率也更高):


不错,但请注意,
Price
Discount
属性是字符串,因为它们是从CSV文件加载的,但您希望将它们按数字排序。不错,但请注意,
Price
Discount
属性是字符串,因为它们是从CSV文件加载的,但你要把它们按数字分类。