Страницы: 1
RSS
PQ. Замена значений по нескольким условиям
 
Добрый день!

Сейчас:
Код
 #"Убрать """ = Table.ReplaceValue(#"Убрать !","""","",Replacer.ReplaceText,{"Арт"}),
    #"Убрать '" = Table.ReplaceValue(#"Убрать ""","'","",Replacer.ReplaceText,{"Арт"}),
    #"Убрать @" = Table.ReplaceValue(#"Убрать '","@","",Replacer.ReplaceText,{"Арт"}),
    #"Убрать #" = Table.ReplaceValue(#"Убрать @","#","",Replacer.ReplaceText,{"Арт"}),
    #"Убрать №" = Table.ReplaceValue(#"Убрать #","№","",Replacer.ReplaceText,{"Арт"}),
    #"Убрать ;" = Table.ReplaceValue(#"Убрать №",";","",Replacer.ReplaceText,{"Арт"}),

А хочется в одну строку... Можно ли в функции  Table.ReplaceValue указать сразу несколько значений для замены?
И можно ли в Table.ReplaceValue при поиске указывать "любой" символ? Например, "Игрушка * медведь", где * может быть любое кол-во символов, например, белый или черный или бурый.
Изменено: Kintoho - 08.08.2018 19:14:49
 
Цитата
Kintoho написал:
Можно ли в функции  Table.ReplaceValue
можно:
= Table.ReplaceValue(#"Убрать!@#", "@!#", ".", (value, old, new)=>Text.Combine(Splitter.SplitTextByAnyDelimiter(Text.ToList(old))(value),new), {"Арт"})
Цитата
Kintoho написал:
можно ли в Table.ReplaceValue при поиске указывать "любой" символ?
можно, но там уже кастомная функция посложнее будет. А что с найденным надо делать?
F1 творит чудеса
 
Доброе время суток
Цитата
Максим Зеленский написал:
Text.Combine(Splitter.SplitTextByAnyDelimiter(Text.ToList
Максим, а не проще ли было
Код
Text.Remove(value, Text.ToList(oldValue))

У ТС же просто удаление символов?
 
Андрей VG, ну если именно удаление, то конечно так проще. Я среагировал на это:
Цитата
Kintoho написал:
указать сразу несколько значений для замены
и в моем примере я заменяю на точку, кстати :)
Изменено: Максим Зеленский - 09.08.2018 12:32:21
F1 творит чудеса
 
Максим Зеленский, Андрей VG, спасибо за ответы!
Цитата
Максим Зеленский написал:
А что с найденным надо делать?
Удалить или поменять на символ как вы и сделали с точкой.
Цитата
Максим Зеленский написал:
= Table.ReplaceValue(#"Убрать!@#", "@!#", ".", (value, old, new)=>Text.Combine(Splitter.SplitTextByAnyDelimiter(Text.ToList(old))(value),new), {"Арт"})
Такой код работает. А можете пояснить суть записи (value, old, new) ? Я правильно понял, что это вызов функции value определяющее выражение которой указано после => и эта функция возвращает единственное значение new ?
Но не понятно как работает 4й параметр в функции ReplaceValue, ведь Значение это #"Убрать!@#" , старое значение это @!#", а новое это "." и тут по идее функция должна быть закрыта.
Replacer.ReplaceValue(value as any,  old as any,  new as any) as any

И ещё я заметил что функция убирает знак ", причём я не прошу PQ его удалять (указываю символы <)(> ), ну или получается, что прошу (ведь без "" указать значения нельзя), но как тогда быть если символ " нужно сохранить в тексте?
Код
let
    Источник = Excel.CurrentWorkbook(){[Name="Остатки"]}[Content],
    #"Замена <)(>" = Table.ReplaceValue(Источник,"<)(>", "!",(value, old, new)=>Text.Combine(Splitter.SplitTextByAnyDelimiter(Text.ToList(old))(value),new),{"Наименование"})
in
    #"Замена <)(>"
Цитата
Андрей VG написал:
Максим, а не проще ли было
Код ? 1Text.Remove(value, Text.ToList(oldValue))
У ТС же просто удаление символов?
Как написать данную конструкцию я пока что не понял, надо дальше вникать в синтаксис языка....
Да, суть задачи - удалить ненужные символы.
 
Цитата
Kintoho написал:
Удалить или поменять
Это всё же разные операции, определитесь.
Цитата
Kintoho написал:
надо дальше вникать в синтаксис языка....
Не только, но и справку читать тоже ;)
Код
Splitter.SplitTextByAnyDelimiter(Text.ToList(old), QuoteStyle.None)
 
Цитата
Kintoho написал:
суть записи (value, old, new)
Примитивное исследование показало, что по умолчанию в функции Table.ReplaceValue используется например, функция Replacer.ReplaceText, принимающая на вход 3 аргумента, в справке по ней обозванные как value, old, new. При этом понятно, что раз мы указываем в Table.ReplaceValue название функции без прямой передачи этих аргументов, значит, Table.ReplaceValue передает эти аргументы где-то внутри, хотя по сути мы их задаем там же в общих аргументах - имя столбца, старое значение, новое значение.  Но сама функция замены нас не устроила, поэтому создали свою функцию, которая также берет три аргумента, в том же порядке.
Код функций (в сокращенном представлении) пишется как (arg1, arg2, ..., argN) => function body. Можно задать типы аргументов и тип возвращаемого значения.
Цитата
(value, old, new)=>Text.Combine(Splitter.SplitTextByAnyDelimiter(Text.ToList(old))(value),new)
ну назвал их тоже value, old, new, хотя изначально они были v, o, n - тут сами имена не важны, важен порядок подачи в функцию.
Изменено: Максим Зеленский - 09.08.2018 18:48:06
F1 творит чудеса
 
Приветствую всех форумчан! Нужна помощь в написании кода в Power Query замены фрагмента списка, при том что заменяемый фрагмент содержит внутри те же разделители, что и весь список. То есть в ряду ячейки содержат список ответственных, разделенных запятыми:
{МВД,МИД, акиматы Алматы, Нур-Султана и областей, НБ},
{Акиматы областей,гг. Алматы, Нур-Султана,МВД,МИД, НБ},
и так далее
и требуется замена по таблице соответствия:
акиматы Алматы, Нур-Султана и областей       = МИО
Акиматы областей,гг. Алматы, Нур-Султана      =МИО
Понятно, что имеется значительно больше чем две строки как в основной таблице, так и в таблице соответствия.
А так получается, что делаю порядка 300 шагов по замене,что сильно тормозит запрос.
И нашел пока единственный выход: на основе этих шагов создал таблицу соответствия полного текста ячеек с исправленными вручную, убрал эти шаги через  через слияние. запросов.
Понимаю, что нужно организовать внутри функции Table.ReplaceValue цикл перебора, но увы не обладаю достаточными знаниями в создании вложенных функций, а тем более с учетом преобразований в лист, преобразованием форматов на лету и так далее. Буду рад любой методической помощи, так как на этом примере хочу понять механизм таких формул и преобразований.
P.S. В теме "Замена значений в PowerQuery, Заменить несколько значений в столбце одним шагом в PQ" решение касается только замены всей ячейки.
Изменено: AzatKukanov - 30.08.2019 19:27:39
 
Вариант.
 
нашел у себя
 
Цитата
artyrH написал:
нашел у себя
а написать для транспортировки? :)
 
Андрей VG,рахмет (спасибо). Сейчас пытаюсь определиться с логикой Вашего кода. arturH также отправил свой вариант с рекурсией. У нас уже ночь. Все остается на завтра. Еще раз спасибо за оперативный ответ.
 
Андрей VG, времени не было. параллельно вебинар смотрел
 
Андрей VG,приветствую.
Попытаюсь изложить понимание Вашего решения:
1.Преобразуем таблицу соответствия в Список:  List.Buffer(Table.ToRecords(Источник))
2. Группируем таблицу исходных данных по столбцу, подлежащему исправлению.Заодно определяем эти группировки как ключ, то есть уникальные. В созданном столбце temp храним сгруппированные таблицы.
3. Преобразуем исходную таблицу формулой Table.TransformColumns, используя в качестве функции трансформации выражение, заключенное в фигурные скобки.
4. В фигурных скобках работает пользовательская функция (source), которая использует в качестве вычисляемого выражения для первой функции List.Accumulate с объявленными аргументами (acc, pair) для листа  функцию замены пар Text.Replace(acc, pair[ВХОД], pair[ВЫХОД]).
Вот тут мне и возникли вопросы:то что Text.Replace передает пары в функции аккумулятора понятно, но где здесь исходный источник, ведь для накопления берется лист ПОДСТАНОВКА. А исходный текст используется только в самой трансформации.
Или эта конструкция работает в итерации: вначале пара из таблицы соответствия (тип List) для замены, потом это передается в исходный текст с накоплением переданной пары в аккумуляторе, потом возвращаемся к аккумулятору, тот запрашивает новую пару (??? - по строке вниз или не совпадающей с уже накопленными парами) и по этой новой паре идет замена в функции трансформации.
5. Разворачиваем полученную на предыдущем шаге таблицу: разворачиваются таблицы столбца temp с колонками "Программы","Задачи" в одноименные столбцы новой таблицы.
6. Приводим таблицу в завершенный вид.
Приношу извинения за возможно технически неграмотный текст, но я не спец в языках программирования. Я чаще всего использую готовые модули с общим пониманием концепта решения. НО... эффективное использование возможностей PQ, PPivot и PBI, на мой взгляд, требуют понимания нюансов соответствия типа данных используемым переменных, понимания механизмов, в том числе внутренних, работы той или иной функции. Иначе как делал я 300 и более шагов, так и буду. И тогда смысл использования надстроек пропадает окончательно. Надеюсь с помощью формучан всетаки освоить хоть какие-то азы
 
Цитата
AzatKukanov написал:
Вот тут мне и возникли вопросы:то что Text.Replace передает пары в функции аккумулятора понятно, но где здесь исходный источник, ведь для накопления берется лист ПОДСТАНОВКА.
(source) =>                                     // текущее значение для замены подается в качестве аргумента на функцию трансформатор для Table.TransformColumns
List.Accumulate(ПОДСТАНОВКА, // итератор, проходит по каждой записи списка
source,                                           // текущее стартовое значение = (source),
(acc, pair) =>                                 // acc = source на первом шаге итерации, будет постоянно меняться так как является одним из аргументов функции Text.Replace,
                                                     // pair = текущему значению из списа-итератора
Text.Replace(acc,                          // является текстом в котором ищется значение для замены
pair[ВХОД],                                    // что ищем
pair[ВЫХОД]))                               // на что заменяем

На выходе остается замененное значение.
Изменено: DrillPipe - 31.08.2019 20:07:54
 
DrillPipe,спасибо за разъяснение.  
 
Цитата
AzatKukanov написал:
спасибо за разъяснение.  
Если хотите посмотреть как это работает можете добавить этот запрос
Код
let
    Source = Table.Group(ПРОГРАММЫ, {"ОТВЕТСТВЕННЫЕ"}, {"temp", each _}),
    corrected = Table.TransformColumns(
                  Source,
                  {"ОТВЕТСТВЕННЫЕ", 
                   (source) => List.Accumulate(
                                ПОДСТАНОВКА, 
                                {[sourceText = source, currentText = source, oldText = "", newText = ""]}, 
                                (acc, pair) => List.Combine(
                                                {acc,
                                                 {[
                                                   sourceText = acc{List.Count(acc)-1}[sourceText], 
                                                   currentText = Text.Replace(acc{List.Count(acc)-1}[currentText], pair[ВХОД], pair[ВЫХОД]),
                                                   oldText = pair[ВХОД], 
                                                   newText = pair[ВЫХОД]
                                                 ]}
                                                }
                                               )
                               )
                  }
                ),
    #"Select step" = corrected{0}[ОТВЕТСТВЕННЫЕ],
    #"To Table" = Table.FromList(#"Select step", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"to Column" = Table.ExpandRecordColumn(#"To Table", "Column1", {"sourceText", "currentText", "oldText", "newText"}, {"sourceText", "currentText", "oldText", "newText"})
in
    #"to Column"
Изменено: DrillPipe - 01.09.2019 00:13:05
 
на https://zen.yandex.ru/media/id/5c7acf0ae8513400b2ceeccf/m-gotovye-resheniia-5e2c92fea1bb8700b092fa8a
опубликован вариант
BulkTextReplace
Код
(x as text) as text =>
let
    maxIterations = Table.RowCount(TranslationTable) ,
    Iterations = List.Generate( () =>
    [Result = Text.Replace(x, TranslationTable[OldText]{0},
    TranslationTable[NewText]{0}), Counter = 0],
    each [Counter] < maxIterations,
    each [Result = Text.Replace([Result], TranslationTable[OldText]{Counter}, TranslationTable[NewText]{Counter}),
    Counter = [Counter] +1], each [Result]),
    output = Iterations{maxIterations-1}
in
    output
Изменено: Kor - 08.02.2020 13:49:13
Страницы: 1
Наверх