Страницы: 1
RSS
Поиск значений из списка в строке с текстом Power Query
 
Добрый день! Коллеги, прошу помощи в решении задачи с помощью Power Query. Во вложении файл с 2 таблицами "Текст" и "Список опций". Необходимо промаркеровать (например с помощью 1) те строки из таблицы "Текст", в которых содержится хотя бы одна текстовая строка из таблицы "Список опций". При этом поиск необходимо осуществлять к конца строки (при наличие разделителя " на " в строке выполнять поиск после него) и исключить влияние регистра.

Для исключения влияния регистра можно использовать функцию Text.Lower() на обе таблицы, а для поиска с конца развернуть текст с помощью Text.Reverse(). А вот что делать дальше ума не приложу.
Изменено: Murderface_ - 17.12.2019 15:01:38
 
Доброе время суток
Цитата
Murderface_ написал:
необходимо осуществлять к конца строки
Не проясните - в чём смысл такого действия? Сам по себе поиск с конца строки - чем важен?
 
Цитата
Андрей VG написал:
проясните
Разумеется. На примере опции "Максимальный". В таблице с текстом есть вот такие строки
Замена пакета с   100354 IPTV Максимальный на 100430 IPTV Для своих;
Замена пакета с 100441 IPTV Для   развлечений на 100323 IPTV Максимальный (Арх.2015);
В первом случае это отключение данной опции, а во втором подключение. Конечная опция всегда находится в конце строки.
Изменено: Murderface_ - 17.12.2019 14:08:02
 
Вариант
Код
let
    data = Excel.CurrentWorkbook(){[Name="Текст"]}[Content],
    words = Excel.CurrentWorkbook(){[Name="Опции"]}[Content][Список опций],
    result = Table.AddColumn(data, "Признак", (rec) =>
    let
        max = List.Max(List.Transform(words, each [word = _, position = Text.PositionOf(Text.Lower(rec[Текст]), Text.Lower(_))]), null, (a, b) => a[position] - b[position])
    in
        if max[position] = -1 then null else max[word]
    )
in
    result

Пути для некоторой оптимизации - имеются.
 
Цитата
Murderface_ написал:
Конечная опция всегда находится в конце строки.
Прекрасно, допустим в вашем списке есть опция "Для своих" (а её там нет), откуда алгоритму знать что в первой строке нужно сначала искать именно "для своих", а потом "Максимальный"? А если в вашем списке эти опции будут расположены наоборот тогда он найдет максимальный справа налево в любом случае для обеих строк.
З.Ы. А хотя, я гляжу, Андрей нашел как эту тему обыграть.
Изменено: PooHkrd - 17.12.2019 14:50:51
Вот горшок пустой, он предмет простой...
 
PooHkrd, вот этот момент я упустил  :( . Действительно неверно же будет выполнятся маркировка. Прошу прощения за некорректную постановку задачи.

Андрей VG, спасибо вам!
 
Murderface_, вариант Андрея я так понимаю вам подойдет только если будет полный исходный справочник всех опций. Так? Если справочник неполный то код рабочий? Находит точно то что хотелось?
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
З.Ы. А хотя, я гляжу, Андрей нашел как эту тему обыграть.
Замена пакета с 100354 IPTV Максимальный на 100351 IPTV Стартовый; вот тут неверно маркируется, но это я виноват. Может быть возможно учитывать наличие разделителя " на " в строке и если он есть, то выполнять поиск после него (до, если искать с конца).
 
Ну вот, вам осталось слегка модифицировать код Андрея и будет работать как надо.
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
осталось слегка модифицировать код Андрея
Всего то  :) . У меня решение Андрея даже на шаги разложить не получается, по тому же примеру как вы мне показывали.
 
Цитата
PooHkrd написал:
слегка модифицировать код Андрея
легко сказано :)
вот как шаг result разложить для теста?
 
Ну, если прямо хочется разложить, то это не так просто. Но если на вскидку, то нужно просто в этом куске
Код
position = Text.PositionOf( Text.Lower( rec[Текст] ), Text.Lower(_) )

добавить Text.AfterDelimiter примерно вот так:
Код
position = Text.PositionOf( Text.AfterDelimiter( Text.Lower( rec[Текст] ), " на " ), Text.Lower(_) )
Изменено: PooHkrd - 17.12.2019 16:22:43
Вот горшок пустой, он предмет простой...
 
Цитата
PooHkrd написал:
добавить Text.AfterDelimiter
Добавил. Но т. к. есть строки, которые не содержат в себе " на ", то эта функция возвращает пустое значение для этих строк и большая часть опций не маркируется  :(
Также при разделителе " на " не будет маркироваться Установка постоянной услуги 64190 Антивирус.Kaspersky Safe Kids на 1 устройство;
Я так понимаю универсального решения не существует  :(  
Изменено: Murderface_ - 18.12.2019 10:40:09
 
Цитата
Murderface_ написал:
Я так понимаю универсального решения не существует
Тут проблема больше с постановкой задачи, лично я до сих пор не понимаю чего вам, собственно, нужно.
По вопросу темы вам Андрей дал готовое красивое решение, но вы до сих пор четко не сформулировали задачу: вот есть, вот чего хочу на выходе.
Вот горшок пустой, он предмет простой...
 
Перенес решение Андрея в рабочий файл, в нем список опций немного другой. Вариант сработал без ошибок, еще раз большое спасибо!
 

Доброе время суток.

1. Воспользовалась алгоритмом написаным в сообщении #4 для поиска текста в строке Power query.

Разобралась во всем, кроме условия (a,b) => a-b в List.Max(). Подскажите, пожалуйста, что это условие призвано решить? Если условие удалить, то все ломается. Пыталась найти какуе-то информацию в интернете. Не нашла. Все мои попытки методом тыка и подбора разобраться ничем не закончились.

2. Необходимо найденный текст в строке заменить на правильный/корректный. Решила вопрос через массовую замену (воспользовалась видео Николая Павлова).

Можно ли как-то упростить решение в прикрепленном файле, а именно объединить два этих решения, чтоб при поиске сразу происходила замена текста на корректный и не создавать много шагов и две колонки с последующем удалением одной(Производитель и КорректПроизвод)?

3. В случае нескольхих вхождений значений в одной строке, текущая реализация выводит последнее вхождение (ближайшее к концу строки). Можно ли как-то изменить данный алгоритм, чтобы выводилось первое вхождение (ближайшее к началу строки)? Или для этого нужен другой медод/код?

Спасибо.

Изменено: Energy+ - 19.03.2021 15:57:19
 
Цитата
Energy+ написал:
Разобралась во всем
Тогда подумайте - у вас есть список записей, вам нужно найти в этом списке такую запись, у которой поле position имеет максимальное значение. Вот именно эту задачу и выполняет анонимная функция в функции List.Max как аргумент optional comparisonCriteria as any
Код
(a, b) => a[position] - b[position]

Цитата
Energy+ написал:
Можно ли как-то упростить решение
А зачем? Цель такого решения в чём? Количество шагов кода - далеко не лучшая причина для того, чтобы заниматься его совершенствованием. Пожалуй, это последнее, чем стоит заниматься в программировании.
Изменено: Андрей VG - 19.03.2021 17:07:25
 
Функция List.Max() возвращает максимальное значение в списке, и при необходимости указать способ сравнения вводится условие. Но в алгоритме из сообщения #4, если не указать условие сравнения функция не работает - выдает ошибку. Я не могу уловить логику.
Я так понимаю, что условие (a,b) => (a[position]-b[position]) сравнивает позицию через получение отрицательного значения, но почему функция не работает без указания условия?
 
Цитата
Energy+ написал:
почему функция не работает без указания условия?
Я написал так много букв?
Цитата
Андрей VG написал:
у вас есть список записей, вам нужно найти в этом списке такую запись
Или что вам в этой фразе не понятно?
Страницы: 1
Наверх