Tcl частичное совпадение строк одного списка с другим

Я пытаюсь найти элементы в списке 1, которые являются частичными совпадениями строки с элементами из списка 2, используя Tcl.

Я использую это, но это очень медленно. Есть ли более эффективный способ сделать это?

set list1 [list abc bcd cde]
set list2 [list ab cd]

set l_matchlist [list]
foreach item1 $list1 {
     foreach item2 $list2 {
          if {[string match -nocase "*${item2}*" $item1]} {
               lappend l_matchlist $item1
               break
          }
     }
}

мои фактические списки очень длинные, и это занимает много времени. Это лучший способ сделать это?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Помимо того, что это медленно, существует также проблема, если list2 содержит элементы с подстановочными знаками, такими как '?' и '*'.

Я ожидаю, что следующий метод будет работать быстрее. По крайней мере, это устраняет проблему, упомянутую выше:

set list1 [list abc BCD ace cde]
set list2 [list cd ab de]

set l_matchlist [list]
foreach item2 $list2 {
    lappend l_matchlist \
      {*}[lsearch -all -inline -nocase -regexp $list1 (?q)$item2]
}

Параметр -regexp в сочетании с (?q) поначалу может показаться странным. Он использует сопоставление с регулярным выражением, а затем сообщает регулярному выражению обработать шаблон как литеральную строку. Но это приводит к частичному совпадению, которое вам нужно.

Это отличается от вашей версии тем, что она может выдавать результаты в другом порядке, и один и тот же элемент из списка1 может быть сообщен несколько раз, если он соответствует более чем одному элементу в списке2.

Если это нежелательно, вы можете продолжить:

set l_matchlist [lmap item1 $list1 {
    if {$item1 ni $l_matchlist} continue
    set item1
}]

Конечно, это уменьшит часть прироста скорости, достигнутого ранее.

Вы можете немного схитрить и превратить задачу обработки списка в задачу обработки строк. Последние обычно немного быстрее в Tcl.

Ниже я сначала превращаю list1 в строку с исходными элементами списка, разделенными символом-разделителем полей ASCII "\x1F". Затем результат можно получить в одном цикле с помощью поиска по регулярному выражению. Регулярное выражение находит первую подстроку, ограниченную символами-разделителями полей, которая содержит item2:

# convert list to string:
set string1 \x1F[join $list1 \x1F]\x1F

set l_matchlist [list]
foreach item2 $list2 {
    # escape out regexp special chars:
    set item2 [regsub -all {\W} $item2 {\\&}]
    # use append to assemble regexp pattern
    set item2 [append x {[^\x1F]*} $item2 {[^\x1F]*}][unset x]
    if {[regexp -nocase $item2 $string1 match]} {
        lappend l_matchlist $match
    }
}

Другие вопросы по теме