Страницы: 1
RSS
Power Query M - Замена значений в таблице по условиям из другой таблицы.
 
Здравствуйте!

Помогите пожалуйста решить простую на первый взгляд (для вас :) ) проблему.

Имеется таблица A со значениями следующего вида:
Скрытый текст

Имеется таблица B с условиями для замены значений в таблице A:
Скрытый текст

По результатам выполнения запроса, должна получиться таблица C (кота заменили на собаку):
Скрытый текст

Столбцы в таблице A могут добавляться новые. Количество условий будет постоянно пополняться в таблице B.

Спасибо заранее!
 
Цитата
Barly написал:
простую на первый взгляд
ну так и нам дайте взглянуть, чего стесняться
Соблюдение правил форума не освобождает от модераторского произвола
 
Barly, если все правильно понял, предлагаю так:
Код
let
    WhatReplace= Excel.CurrentWorkbook(){[Name="NomToReplace"]}[Content],
    MergedOldNew = Table.CombineColumns(WhatReplace,{"Old_Item", "New_Item"},(x)=>x,"merged"),
    GroupedRows = Table.Group(MergedOldNew, {"Unique_Key"}, {{"tab", each 
        let a = Table.Group(_, {"Unique_Key", "Column_to_Replace"}, {"merged", each [merged]}) 
        in  Table.FromRows({ {a[Unique_Key]{0}} & a[merged] }, {"repUnique_Key"} & List.Transform( a[Column_to_Replace], each "rep"&_) ), type table}}),
    Custom = Table.Combine( GroupedRows[tab] ),
    Source = Table.RemoveColumns( Table.Join( Excel.CurrentWorkbook(){[Name="tbl"]}[Content], "Unique_Key", Custom, "repUnique_Key", JoinKind.LeftOuter ), {"repUnique_Key"} ),
    fn = (t as table)=>
        let repHeader = Text.Range( List.Select( Table.ColumnNames( t ), each Text.StartsWith( _, "rep" ) ){0}?, 3 ),
            out = if repHeader = null 
                then t
                else @fn( Table.CombineColumns( t, {repHeader, "rep" & repHeader}, (x)=> if x{1} = null then x{0} else List.ReplaceMatchingItems({x{0}}, x{1}){0}, repHeader ) )
        in  out,
    Result = fn( Source )
in
    Result
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
если все правильно понял, предлагаю так:
PooHkrd, Огромное спасибо! То, что нужно!
 
PooHkrd, изящно, но много незнакомых приемов, связанных с синтаксисом языка М, подскажите, где можно подробнее почитать, буду признателен
 
Владимир Колотиев, какие именно моменты не понятны, покажите, а то я таскал отовсюду понемножку. Но, кстати, главный мой источник - форум и решения/советы здешних обитателей. Здесь публиковалось много ссылок на разное и в том числе на книжки
Изменено: PooHkrd - 19.01.2021 14:12:49
Вот горшок пустой, он предмет простой...
 
PooHkrd, вот эти конструкции не понятны
Код
(x)=>x,"merged")

GroupedRows = Table.Group(MergedOldNew, {"Unique_Key"}, {{"tab", each 
        let a = Table.Group(_, {"Unique_Key", "Column_to_Replace"}, {"merged", each [merged]}) 
        in  Table.FromRows({ {a[Unique_Key]{0}} & a[merged] }, {"repUnique_Key"} & List.Transform( a[Column_to_Replace], each "rep"&_) ), type table}}),
 
Владимир Колотиев, ну что ж рад что про рекурсию в коде ниже все ясно.
В выделенном вами фрагменте как раз все не так сложно,
Смысл задачи в том, чтобы сделать Table.Pivot и в результате получить столбцы с составными значениями, которые потом можно передать в List.RelaceMatchingItems. Но Table.Pivot "из коробки" не умеет выдавать в агрегируемых ячейках списки (т.к. это составной тип) поэтому используем Table.Group и внутри него сначала группируемся по названию столбцов замены, а потом при помощи Table.FromRows разворачиваем строки в столбцы с одновременным их переименованием.
В принципе пока расписывал, попробовал немножко другой подход, он несколько проще для понимания, так как не содержит много вложенных конструкций. Я почему то думал, что это именно функция не поддерживает вывод составных значений в результате, но оказалось что это заглушка на уровне интерфейса, а вручную там можно нагородить чего хочешь.
Код
let
    WhatReplace= Excel.CurrentWorkbook(){[Name="NomToReplace"]}[Content],
    MergedOldNew = Table.CombineColumns(WhatReplace,{"Old_Item", "New_Item"},(x)=>x,"merged"),
    PivotedColumn = Table.Pivot(MergedOldNew, List.Distinct(MergedOldNew[Column_to_Replace]), "Column_to_Replace", "merged", (x)=>x),
    RenamedColumns = Table.PrefixColumns(PivotedColumn, "rep"),
    Source = Table.RemoveColumns( Table.Join( Excel.CurrentWorkbook(){[Name="tbl"]}[Content], "Unique_Key", RenamedColumns, "rep.Unique_Key", JoinKind.LeftOuter ), {"rep.Unique_Key"} ),
    fn = (t as table)=>
        let repHeader = Text.Range( List.Select( Table.ColumnNames( t ), each Text.StartsWith( _, "rep." ) ){0}?, 4 ),
            out = if repHeader = null 
                then t
                else @fn( Table.CombineColumns( t, {repHeader, "rep." & repHeader}, (x)=> if x{1} = null then x{0} else List.ReplaceMatchingItems({x{0}}, x{1}){0}, repHeader ) )
        in  out,
    Result = fn( Source )
in
    Result

Если вас интересует именно использование синтаксиса языка, то вот здесь очень доходчивая русскоязычная статья, и там есть еще продолжение, тоже интересно.
Изменено: PooHkrd - 21.01.2021 19:39:15
Вот горшок пустой, он предмет простой...
Страницы: 1
Наверх