Удалите перекрывающиеся подстроки в поле BigQuery STRING - PullRequest
1 голос
/ 22 апреля 2020

Я пытаюсь найти наиболее эффективный способ удаления перекрывающихся подстрок из значения строкового поля в BigQuery. Мой вариант использования такой же, как Объединение нескольких подстановок регулярных выражений , но внутри BigQuery.

Если я подведу итог вышеприведенному посту:

Со следующим списком подстрок: ["quick brown fox", "fox jumps"]

Я хочу:

A quick brown fox jumps over the lazy dog заменить на A over the lazy dog.

Я думал о том, чтобы придумать JS UDF, который выполняет аналогичную работу чем то, что упомянуто в посте выше, т.е. создать маску всей строки и l oop поверх подстрок, чтобы определить, какие символы удалить ... Но у вас есть лучшие идеи?

Спасибо за вашу помощь

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Я не смог выяснить, как это сделать в стандарте SQL

Ниже приведено описание стандарта BigQuery SQL, и все это делается одним выстрелом - всего один [простой ] запрос

#standardSQL
WITH `project.dataset.table` AS (
  SELECT 'A quick brown fox jumps over the lazy dog' text 
), list AS (
  SELECT ['quick brown fox', 'fox jumps'] phrases
)
SELECT text AS original_text, REGEXP_REPLACE(text, STRING_AGG(pattern, '|'), '') processed_text FROM (
 SELECT DISTINCT text, SUBSTR(text, MIN(start),  MAX(finish) - MIN(start) + 1) pattern FROM (
  SELECT *, COUNTIF(flag) OVER(PARTITION BY text ORDER BY start) grp FROM (
   SELECT *, start > LAG(finish) OVER(PARTITION BY text ORDER BY start) flag FROM (
    SELECT *, start + phrase_len - 1 AS finish FROM (
     SELECT *, LENGTH(cut) + 1 + OFFSET * phrase_len + IFNULL(SUM(LENGTH(cut)) OVER(win), 0) start
     FROM `project.dataset.table`, list, 
     UNNEST(phrases) phrase, 
     UNNEST([LENGTH(phrase)]) phrase_len,
     UNNEST(REGEXP_EXTRACT_ALL(text, r'(.+?)' || phrase)) cut WITH OFFSET
     WINDOW win AS (PARTITION BY text, phrase ORDER BY OFFSET ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) 
 )))) GROUP BY text, grp
) GROUP BY text

с выводом

Row original_text                               processed_text   
1   A quick brown fox jumps over the lazy dog   A over the lazy dog    

Я тестировал выше с несколькими более сложными / хитрыми текстами, и он все еще работал

Краткое объяснение:

  1. собирает все включения фраз в список и их соответствующие начала и конца
  2. объединяет перекрывающиеся фрагменты и вычисляет их соответствующие начала и конца
  3. извлекает новые фрагменты, основываясь на начале и конце указанного выше шага 2
  4. упорядочьте DES C их по длине и сгенерируйте выражение регулярного выражения
  5. наконец выполните REGEXP_REPLACE, используя регулярное выражение, сгенерированное на шаге 4 выше

Выше может выглядеть грязно - но на самом деле все это делается в одном запросе и в чистом виде SQL

1 голос
/ 22 апреля 2020

Использование пользовательского JS UDF, кажется, работает, но я видел более быстрый BigQuery ..!

    CREATE FUNCTION `myproject.mydataset.keyword_remover_js`(label STRING) RETURNS STRING LANGUAGE js AS """

    var keywords = ["a quick brown fox", "fox jumps"] ;

    var mask = new Array(label.length).fill(1);
    var reg = new RegExp("(" + keywords.join("|") + ")", 'g');
    var found;

    while (found = reg.exec(label)) { 

        for (var i = found.index; i < reg.lastIndex; i++) {
            mask[i] = 0;
            }
        reg.lastIndex = found.index+1;
    }

    var result = []

    for (var i = 0; i < label.length; i++) {
        if (mask[i]) {
            result.push(label[i])
        }
    }

    return result.join('').replace(/ +/g,' ').replace(/^ +| +$/,'')
    """;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...