Разделить и подсчитать
Вы можете разделить строку по фразе и вычесть 1 из счета. Это работает для любой подстроки, что, с другой стороны, означает, что она не соблюдает границы слов.
LET things = [
{name: "Here are SomeSome and Some Other Things, brOther!"},
{name: "There are no such substrings in here."},
{name: "some-Other-here-though!"}
]
FOR t IN things
LET Some = LENGTH(SPLIT(t.name, "Some"))-1
LET Other = LENGTH(SPLIT(t.name, "Other"))-1
LET Thing = LENGTH(SPLIT(t.name, "Thing"))-1
RETURN {
Some, Other, Thing
}
Результат:
[
{
"Some": 3,
"Other": 2,
"Thing": 1
},
{
"Some": 0,
"Other": 0,
"Thing": 0
},
{
"Some": 0,
"Other": 1,
"Thing": 0
}
]
Вы можете использовать SPLIT(LOWER(t.name), LOWER("..."))
, чтобы сделать регистр нечувствительным.
СОБИРАЙ слова
Функцию TOKENS()
можно использовать для разделения ввода на массивы слов, которые затем можно сгруппировать и подсчитать. Обратите внимание, что я немного изменил ввод. Вход "SomeSome"
не будет засчитан, потому что "somesome" != "some"
(этот вариант основан на словах, а не на подстроках).
LET things = [
{name: "Here are SOME some and Some Other Things. More Other!"},
{name: "There are no such substrings in here."},
{name: "some-Other-here-though!"}
]
LET whitelist = TOKENS("Some Other Things", "text_en")
FOR t IN things
LET whitelisted = (FOR w IN TOKENS(t.name, "text_en") FILTER w IN whitelist RETURN w)
LET counts = MERGE(FOR w IN whitelisted
COLLECT word = w WITH COUNT INTO count
RETURN { [word]: count }
)
RETURN {
name: t.name,
some: counts.some || 0,
other: counts.other || 0,
things: counts.things ||0
}
Результат:
[
{
"name": "Here are SOME some and Some Other Things. More Other!",
"some": 3,
"other": 2,
"things": 0
},
{
"name": "There are no such substrings in here.",
"some": 0,
"other": 0,
"things": 0
},
{
"name": "some-Other-here-though!",
"some": 1,
"other": 1,
"things": 0
}
]
При этом используется подзапрос для COLLECT, иначе будет подсчитано общее количество вхождений для всего ввода.
Шаг в белый список не является обязательным, вы также можете позволить ему подсчитывать все слова. Для больших входных строк это может сэкономить немного памяти, чтобы не делать этого для слов, которые вас все равно не интересуют.
Возможно, вы захотите создать отдельный Анализатор с отключенным стеммингом для языка, если вы хотите точно сопоставить слова. Вы также можете отключить нормализацию ("accent": true, "case": "none"
). Альтернативой может быть использование REGEX_SPLIT()
для типичных пробелов и знаков препинания для упрощения токенизации, но это зависит от вашего варианта использования.
Другие решения
Я не думаю, что можно подсчитывать каждый входной объект независимо с помощью COLLECT без подзапроса, если вам не нужен общий счет.
Разделение - это своего рода хитрость, но вы можете заменить SPLIT () на REGEX_SPLIT () и заключить поисковые фразы в \b
, чтобы они соответствовали только тем, что границы слова находятся с обеих сторон. Тогда он должен соответствовать только словам (более или менее):
LET things = [
{name: "Here are SomeSome and Some Other Things, brOther!"},
{name: "There are no such substrings in here."},
{name: "some-Other-here-though!"}
]
FOR t IN things
LET Some = LENGTH(REGEX_SPLIT(t.name, "\\bSome\\b"))-1
LET Other = LENGTH(REGEX_SPLIT(t.name, "\\bOther\\b"))-1
LET Thing = LENGTH(REGEX_SPLIT(t.name, "\\bThings\\b"))-1
RETURN {
Some, Other, Thing
}
Результат:
[
{
"Some": 1,
"Other": 1,
"Thing": 1
},
{
"Some": 0,
"Other": 0,
"Thing": 0
},
{
"Some": 0,
"Other": 1,
"Thing": 0
}
]
Более элегантным решением было бы использовать ArangoSearch для подсчета слов, но у него нет функции, позволяющей узнать, как часто встречается слово. Он может отслеживать это уже внутренне (функция анализатора "частота"), но определенно не отображается в данный момент.
person
CodeManX
schedule
16.01.2020
x = y = z
) - person CodeManX   schedule 15.01.2020FOR t IN thing COLLECT name = t.name WITH COUNT INTO count RETURN { name, count }
. - person Bjorn Thor Jonsson   schedule 15.01.2020