Forum Discussion

Dicken's avatar
Dicken
Post Prodigy
6 months ago
Solved

Power Query Distinct non repeating Index

Hi, is there a way in power query to create a non repeating, distince index,   so the first of each value is counted,  but just blank or null for rest,  so no use grouping adding index to group an...
  • ronrsnfld's avatar
    6 months ago

    List.Generate should work quite rapidly:

    let
      Source = #table(
        type table [Item = text, dex = Int64.Type],
        {
          {"A", 1},
          {"B", 2},
          {"C", 3},
          {"C", 4},
          {"C", 5},
          {"D", 6},
          {"D", 7},
          {"E", 8},
          {"A", 9},
          {"B", 10}
        }),
    
    //Sort by Item
        #"Sorted Rows" = Table.Sort(Source,{{"Item", Order.Ascending}}),
    
    //Add the N column using List.Generate
      #"Add N" = 
          Table.FromColumns(
            Table.ToColumns(#"Sorted Rows")
            & {[i=#"Sorted Rows"[Item],
                  b=List.Generate(
                      ()=>[a=1, idx=0],
                      each [idx]<List.Count(i),
                      each [idx=[idx]+1, 
                            a=if i{idx} = i{idx-1} 
                              then null 
                              else List.Count(List.Distinct(List.Range(i,0,idx+1)))],
                      each [a]
                  )][b]},
            type table[Item=text, dex=Int64.Type, N=Int64.Type]),
    
    //Sort back to original order using the dex column
        #"Sorted Rows1" = Table.Sort(#"Add N",{{"dex", Order.Ascending}})
    in
        #"Sorted Rows1"

     

  • MarkLaf's avatar
    6 months ago

    This groups and adds an index, but then combines as columns which results in getting N just once per group. No idea how this performs vs other solutions provided - test on your data and let us know!

     

    let
      Source = #table(
        type table [Item = text, dex = Int64.Type],
        {
          {"A", 1},{"B", 2},{"C", 3},{"C", 4},{"C", 5},
          {"D", 6},{"D", 7},{"E", 8},{"A", 9},{"B", 10}
        }
      ),
        Group = Table.Group(Source, {"Item"}, {{"rows", Table.ToColumns, type {list} }}),
        Index = Table.AddIndexColumn(Group, "N", 1, 1, Int64.Type),
        IndexToCol = Table.TransformColumns(Index,{{"N", each {{_}} , type {{Int64.Type}}}}),
        CombineCols = Table.CombineColumns( 
          IndexToCol, {"rows","N"}, 
          each Table.FromColumns( 
            List.Combine( _ ), 
            type table Type.ForRecord( 
              Type.RecordFields( Type.TableRow( Value.Type( Source ) ) ) 
              & [N=[Type=Int64.Type,Optional=false]], false 
            ) 
          ), 
          "new_tables" 
        ),
        CombineTables = Table.Combine( CombineCols[new_tables] )
    in
        CombineTables

     

    Output

     

     

  • AlienSx's avatar
    6 months ago

    just List.Generate

    let
      Source = #table(
        {"Item", "dex"},
        {{"A", 1},{"B", 2},{"C", 3},{"C", 4},{"C", 5}, {"D", 6},{"D", 7},{"E", 8},{"A", 9},{"B", 10}}
      ),
      all_items = List.Buffer(Source[Item]),
      distinct_items = List.Distinct(all_items),
      gnr = List.Generate(
        () => [i = 0, contains = true, s = List.RemoveItems(distinct_items, {all_items{0}}), c = 1],
        (x) => x[i] < List.Count(all_items),
        (x) => [
          i = x[i] + 1, 
          contains = List.Contains(x[s], all_items{i}),
          s = if contains then List.RemoveItems(x[s], {all_items{i}}) else x[s],
          c = if contains then x[c] + 1 else x[c]
        ],
        (x) => if x[contains] then x[c] else null
      ),
      n = Table.FromColumns(Table.ToColumns(Source) & {gnr}, Table.ColumnNames(Source) & {"N"})
    in
      n