Russian Qt Forum
Май 21, 2024, 17:13 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3   Вниз
  Печать  
Автор Тема: Найти префикс  (Прочитано 17091 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Август 05, 2016, 11:39 »

Добрый день

Вроде сопливая задачка, а писать приходится не так уж мало. Есть std::vector<std::string> нужно узнать, начинаются ли все строки с какого-то имени (префикса). напр
Код
C++ (Qt)
Zombie_Hip
Zombie_RightLeg
Zombie_LeftArm
..
// префикс Zombie_
 
Ну и требования "здравого смысла" - префикс не может оканчиваться буквой или цифрой (напр если все начинаются с "A", но это еще не префикс). Вот собсно и все - но как-то "не ложится". Прошу блеснуть  Улыбающийся

Спасибо
Записан
Bepec
Гость
« Ответ #1 : Август 05, 2016, 11:51 »

Не блесну, простой проход по строке с окончанием на "не букве не цифре", а потом сравнение полученной строки в следующих итерациях вас не устраивает?
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #2 : Август 05, 2016, 11:52 »

Тут надо уточнить.
Префикс известен заранее? Т.е. надо искать конкретное вхождение?
Или префикс надо выделить из набора строк?
Тогда придется сравнивать все строки до ближайшего несовпадения и потом брать минимальный найденный индекс.
Строка от 0 до этого индекса и будет префиксом.

Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #3 : Август 05, 2016, 11:54 »

Код
C++ (Qt)
#include <iostream>
#include <vector>
#include <algorithm>
 
 
   std::vector<std::string> strings;
   strings.push_back("Zombie_Hip");
   strings.push_back("Zombie_RightLeg");
   strings.push_back("Zombie_LeftArm");
 
   bool all = std::all_of(strings.begin(), strings.end(), [](std::string str){ return str.find("Zombie_") == 0; });
   std::cout << all;  // 1
 
 
   strings.push_back("Vasya_LeftArm");
   all = std::all_of(strings.begin(), strings.end(), [](std::string str){ return str.find("Zombie_") == 0; });
   std::cout << '\n';
   std::cout << all;  // 0
 

Или, руками в цикле:

Код
C++ (Qt)
bool my_all_of(const std::vector<std::string>& strings, const std::string& prefix) {
   for (std::string text: strings) {
       if (text.find(prefix) != 0) {
           return false;
       }
   }
 
   return true;
}


Если я неправильно понял и нужно сначала найти префикс, тогда нужно завести правило по которому префикс находится, например:
Набор символов a-zA-Z до первого встреченного символа '_' слева от строки. Тогда проблем с нахождением не будет
« Последнее редактирование: Август 05, 2016, 12:02 от gil9red » Записан

Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Август 05, 2016, 12:11 »

Или префикс надо выделить из набора строк?
Если я неправильно понял и нужно сначала найти префикс, тогда нужно завести правило по которому префикс находится, например:
Набор символов a-zA-Z до первого встреченного символа '_' слева от строки. Тогда проблем с нахождением не будет
Конечно надо найти, вот (эмпирическое) правило
Ну и требования "здравого смысла" - префикс не может оканчиваться буквой или цифрой (напр если все начинаются с "A", но это еще не префикс).
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #5 : Август 05, 2016, 12:22 »

Если перевести в регулярку, то кажется получается такое правило: ^([\da-zA-Z]+[^\da-zA-Z]+)
Записан

Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #6 : Август 05, 2016, 15:23 »

1. Сравниваем первую строку с остальными до ближайшего несовпадения.
2. Берем минимальный найденный индекс.
3. Смотрим от него "назад" до первого символа, не являющегося буквой или цифрой.
4. профит )
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Август 05, 2016, 17:02 »

Если перевести в регулярку, то кажется получается такое правило: ^([\da-zA-Z]+[^\da-zA-Z]+)
Цитировать
Too old to rock 'n' roll: too young to die
Улыбающийся

1. Сравниваем первую строку с остальными до ближайшего несовпадения.
2. Берем минимальный найденный индекс.
3. Смотрим от него "назад" до первого символа, не являющегося буквой или цифрой.
4. профит )
Не, ну "принципиально" я со всем этим согласен. Но вот реализация выходит какой-то длинной и занудной  Плачущий
Записан
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #8 : Август 05, 2016, 18:18 »

ну, а шо делать)
да в принципе не так и много писать, если подумать.
пара простых циклов.
дольше обсужаем, как мне кажется Улыбающийся
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #9 : Август 05, 2016, 20:14 »

Ну ожидаемо, что уж там.. задача слегка вышла за пределы обычного парсига тел. номеров и тут же возникла целая тема на форуме..
Сформулируйте грамотно правила для разбора префиксов и spirit вам в помощь..) 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Bepec
Гость
« Ответ #10 : Август 05, 2016, 21:42 »

Он имеет в виду - сделайте так, чтобы код был красивым, чтобы его было мало, чтобы он покрывал все сценарии использования, чтобы был самодокументируемым на сто %, чтобы использовать его мог человек без знания ЯП, максимально кроссплатформенным, максимально оптимизированным под каждую платформу, но без платформозависимого кода и при копировании в любое место любого исходника на любом языке программирования выполнял свою задачу.

Ах да, забыл - и ещё чтоб нравится Igors просто так Веселый
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #11 : Август 05, 2016, 22:17 »

Он имеет в виду - сделайте так, чтобы код был красивым, чтобы его было мало, чтобы он покрывал все сценарии использования, чтобы был самодокументируемым на сто %, чтобы использовать его мог человек без знания ЯП, максимально кроссплатформенным, максимально оптимизированным под каждую платформу, но без платформозависимого кода и при копировании в любое место любого исходника на любом языке программирования выполнял свою задачу.
И и и...и? На спирите это не красиво? Не читабельно? Не переносимо? Или много кода? Да, серьёзно? Ну предложите свой вариант, а мы посмотрим) 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #12 : Август 05, 2016, 23:31 »

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

во-первых - это, по сути, другой язык.
во-вторых - это дополнительная зависимость.
в-третьих - хз что там за таргет-платформа, может быть важен вопрос переносимости.
в-четвертых, работы на 10 минут - а уже день обсуждаем Улыбающийся

ЗЫ. Вот загуглил и: http://yumei165.blogspot.de/2013/04/longest-common-prefix-c-code.html
« Последнее редактирование: Август 05, 2016, 23:43 от Racheengel » Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Август 06, 2016, 05:28 »

в-четвертых, работы на 10 минут - а уже день обсуждаем Улыбающийся
Ну так чего ж Вы не пишете?  Улыбающийся

Придумалось, вот опорная ф-ция
Код
C++ (Qt)
bool TestMatch( std::string & src0, const std::string & src1 )
{
// find matched strings start
size_t len, maxLen = qMin(src0.size(), src1.size());
for (len = 0; len < maxLen; ++len)
if (src0[len] != src1[len]) break;
src0.resize(len);
 
// src0 end can't be a letter or digit
while (src0.size()) {
size_t last = src0.size() - 1;
QChar ch = src0[last];
if (ch.isLetter() || ch.isDigit())
src0.resize(last);
else
break;
}
return src0.size() > 0;
}
 
Именно первый аргумент по неконстантной ссылке - тогда все сопли уходят
Код
C++ (Qt)
std::string GetPrefix( const std::vector<std::string> & vec )
{
 if (vec.size() < 2) return std::string();
 std::string match = vec[0];  // копируем первую строку
 
 for (size_t i = 1; i < vec.size(); ++i)
   if (!TestMatch(match, vec[i])) break;
 
return march;
}

И и и...и? На спирите это не красиво? Не читабельно? Не переносимо? Или много кода? Да, серьёзно?
Причем тут спырыт Непонимающий Ну да ладно, "назвались груздем" - предъявляйте решение на spirit
« Последнее редактирование: Август 06, 2016, 05:44 от Igors » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #14 : Август 06, 2016, 05:43 »

Вот Вы рассказывали как начинали с ассемблера и до сих пор следите чтобы код был "нежирный" - и мое сердце радовалось Улыбающийся Ну как же Вы не постеснялись привести реализацию с пере-созданием строки на каждой итерации?  Плачущий

Поиск "готовых решений" засасывает, появляется неуемное желание "жрать", причем все подряд, хорошее/плохое - неважно, главное что "готовое"
Записан
Страниц: [1] 2 3   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.254 секунд. Запросов: 22.