Проверка, что строка равна одному из значений
От: Lonely Dog Россия  
Дата: 23.03.19 07:49
Оценка:
Добрый день!

Есть следующий код:
if (status == "1234" ||
    status == "2345" || 
    status == "3456")
{
 // do something
}


В реальности, в этом if гораздо больше условий. На питоне я бы написал это так:
if status in ["1234", "2345", "3456"]:
  # do something


А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?
Отредактировано 23.03.2019 7:59 Lonely Dog . Предыдущая версия .
Re: Проверка, что строка равна одному из значений
От: kov_serg Россия  
Дата: 23.03.19 07:54
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Добрый день!


LD>В реальности, в этом if гораздо больше условий. На питоне я бы написал это так:

LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?
if (confirms_all_conditions(status)) // ...
Re[2]: Проверка, что строка равна одному из значений
От: Lonely Dog Россия  
Дата: 23.03.19 07:57
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Здравствуйте, Lonely Dog, Вы писали:


LD>>Добрый день!


LD>>В реальности, в этом if гораздо больше условий. На питоне я бы написал это так:

LD>>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?
_>
_>if (confirms_all_conditions(status)) // ...
_>

так а дальше что? в функции будет тот же самый большой if с кучей условий
Re: Проверка, что строка равна одному из значений
От: Пирожочек  
Дата: 23.03.19 07:59
Оценка: +1 -4
Здравствуйте, Lonely Dog, Вы писали:

LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


if (std::hash_set<std::string> {
      "1234", "2345", "3456"
    }.count(status))
{
  // do something
}
Re: Проверка, что строка равна одному из значений
От: LaptevVV Россия  
Дата: 23.03.19 08:33
Оценка: +1 -1
LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?
Радость ты моя, а заранее все эти строки запихать в контейнер — никак?
Вместо вложенных ифов — просто найти в контейнере и сделать, чего с ним связано.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Проверка, что строка равна одному из значений
От: Lonely Dog Россия  
Дата: 23.03.19 08:45
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LD>>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?

LVV>Радость ты моя, а заранее все эти строки запихать в контейнер — никак?
LVV>Вместо вложенных ифов — просто найти в контейнере и сделать, чего с ним связано.
Да можно наверное. Что-нибудь типа такого?

bool isStringInSet(const std::initializer_list<std::string> &options, const std::string &value)
{
  return std::find(std::begin(options), std::end(options), value) != std::end(options);
}

int main()
{
  if (isStringInSet({ "4321", "1234", "1111", "45423534534" }, "1234"))
    std::cout << "IN SET";
  return 0;
}


Хотелось просто более лаконично
Отредактировано 23.03.2019 8:46 Lonely Dog . Предыдущая версия .
Re[3]: Проверка, что строка равна одному из значений
От: niXman Ниоткуда https://github.com/niXman
Дата: 23.03.19 08:51
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>
LD>bool isStringInSet(const std::initializer_list<std::string> &options, const std::string &value)
LD>{
LD>  return std::find(std::begin(options), std::end(options), value) != std::end(options);
LD>}

LD>int main()
LD>{
LD>  if (isStringInSet({ "4321", "1234", "1111", "45423534534" }, "1234"))
LD>    std::cout << "IN SET";
LD>  return 0;
LD>}
LD>


линейная сложность.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: Проверка, что строка равна одному из значений
От: DenisCh Россия  
Дата: 23.03.19 08:54
Оценка: +2
Здравствуйте, Lonely Dog, Вы писали:

LD> LD>>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


LD> LVV>Радость ты моя, а заранее все эти строки запихать в контейнер — никак?

LD> LVV>Вместо вложенных ифов — просто найти в контейнере и сделать, чего с ним связано.
LD> Да можно наверное. Что-нибудь типа такого?
LD>
LD> bool isStringInSet(const std::initializer_list<std::string> &options, const std::string &value)
LD> {
LD>   return std::find(std::begin(options), std::end(options), value) != std::end(options);
LD> }
LD> int main()
LD> {
LD>   if (isStringInSet({ "4321", "1234", "1111", "45423534534" }, "1234"))
LD>     std::cout << "IN SET";
LD>   return 0;
LD> }
LD>

LD> Хотелось просто более лаконично

На мой необразованный, испорченный си с классами, взгляд — это самое нормальное. И самое поддерживаемое.
[url=https://github.com/abbat/avalon1.0.449[/url]
Re[4]: Проверка, что строка равна одному из значений
От: DenisCh Россия  
Дата: 23.03.19 08:55
Оценка:
Здравствуйте, niXman, Вы писали:

X> LD>
X> LD>bool isStringInSet(const std::initializer_list<std::string> &options, const std::string &value)
X> LD>{
X> LD>  return std::find(std::begin(options), std::end(options), value) != std::end(options);
X> LD>}
X> LD>int main()
X> LD>{
X> LD>  if (isStringInSet({ "4321", "1234", "1111", "45423534534" }, "1234"))
X> LD>    std::cout << "IN SET";
X> LD>  return 0;
X> LD>}
X> LD>

X> линейная сложность.

А что, это можно сделать быстрее, чем О(n) ?
Поделись мудростью.
[url=https://github.com/abbat/avalon1.0.449[/url]
Re: Проверка, что строка равна одному из значений
От: niXman Ниоткуда https://github.com/niXman
Дата: 23.03.19 08:58
Оценка:
в пайтон стиле:
    if ( static const std::set<std::string> set{"1234", "4321"}; set.count("1234") ) {
        std::cout << 1 << std::endl;
    } else {
        std::cout << 0 << std::endl;
    }
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: Проверка, что строка равна одному из значений
От: Lonely Dog Россия  
Дата: 23.03.19 09:00
Оценка:
Здравствуйте, niXman, Вы писали:

X>линейная сложность.

Само собой. Но когда вариантов не так много (не забываем, что раньше в коде была куча условий в одном if, и тоже линейная сложность), то это вполне допустимо. Тем более, создание hash_set (или еще чего-нибудь) займет явно больше времени, чем простой проход по этому списку.
Re[5]: Проверка, что строка равна одному из значений
От: niXman Ниоткуда https://github.com/niXman
Дата: 23.03.19 09:05
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>... создание hash_set (или еще чего-нибудь) займет явно больше времени, чем простой проход по этому списку.

посмотрите мой пример, в нем set будет инициализирован только один раз.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: Проверка, что строка равна одному из значений
От: Lonely Dog Россия  
Дата: 23.03.19 09:24
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, Lonely Dog, Вы писали:


LD>>... создание hash_set (или еще чего-нибудь) займет явно больше времени, чем простой проход по этому списку.

X>посмотрите мой пример, в нем set будет инициализирован только один раз.
Посмотрел, осознал. Спасибо.
Re[5]: Проверка, что строка равна одному из значений
От: LuciferSaratov Россия  
Дата: 23.03.19 09:56
Оценка: +1
Здравствуйте, DenisCh, Вы писали:

DC>А что, это можно сделать быстрее, чем О(n) ?

DC>Поделись мудростью.

можно список строк (или их хэшей) заранее отсортировать и искать в нем двоичным поиском, например.
Re[6]: Проверка, что строка равна одному из значений
От: DenisCh Россия  
Дата: 23.03.19 10:46
Оценка:
Здравствуйте, LuciferSaratov, Вы писали:

LS> DC>А что, это можно сделать быстрее, чем О(n) ?

LS> DC>Поделись мудростью.
LS> можно список строк (или их хэшей) заранее отсортировать и искать в нем двоичным поиском, например.

А сортировка строк быстрее?
[url=https://github.com/abbat/avalon1.0.449[/url]
Re[7]: Проверка, что строка равна одному из значений
От: LuciferSaratov Россия  
Дата: 23.03.19 10:50
Оценка: +1
Здравствуйте, DenisCh, Вы писали:

DC>А сортировка строк быстрее?


ну дык в вопросе топикстартера список предполагается быть заранее заданным и неизменным в процессе работы программы, поэтому его можно или сразу задать отсортированным, либо отсортировать один раз перед началом работы.
Re[4]: Проверка, что строка равна одному из значений
От: _NN_ www.nemerleweb.com
Дата: 23.03.19 14:31
Оценка:
Здравствуйте, niXman, Вы писали:


X>линейная сложность.

Python код также будет с линейной сложностью в этом примере
if status in ["1234", "2345", "3456"]:
  # do something
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Проверка, что строка равна одному из значений
От: niXman Ниоткуда https://github.com/niXman
Дата: 23.03.19 14:58
Оценка: -1
Здравствуйте, _NN_, Вы писали:

_NN>Python код также будет с линейной сложностью в этом примере


в пайтоне это норма, но мы в плюсах так не делаем.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[6]: Проверка, что строка равна одному из значений
От: _NN_ www.nemerleweb.com
Дата: 23.03.19 15:07
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, _NN_, Вы писали:


_NN>>Python код также будет с линейной сложностью в этом примере


X>в пайтоне это норма, но мы в плюсах так не делаем.

Лёгким движением [1,2,3] заменяем на {1,2,3} и получаем в пайтоне быстрый поиск.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Проверка, что строка равна одному из значений
От: niXman Ниоткуда https://github.com/niXman
Дата: 23.03.19 15:09
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Лёгким движением [1,2,3] заменяем на {1,2,3} и получаем в пайтоне быстрый поиск.

но ни один питонщик об этом не задумается.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[8]: Проверка, что строка равна одному из значений
От: _NN_ www.nemerleweb.com
Дата: 23.03.19 15:26
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, _NN_, Вы писали:


_NN>>Лёгким движением [1,2,3] заменяем на {1,2,3} и получаем в пайтоне быстрый поиск.

X>но ни один питонщик об этом не задумается.

Для коротких списков действительно set не очень полезен, к тому же занимает до 10ти раз больше памяти ( https://stackoverflow.com/questions/13547883/is-python-set-more-space-efficient-than-list/54891295#54891295 )
Кстати для неизменяемого списка в пайтоне вообще лучше задействовать tuple.
В общем случае, конечно, лучше использовать set, но я не нашёл в PyLint такого правила, а значит никому оно действительно не надо
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Проверка, что строка равна одному из значений
От: AleksandrN Россия  
Дата: 25.03.19 08:14
Оценка: +1
Здравствуйте, DenisCh, Вы писали:

X>> линейная сложность.


DC>А что, это можно сделать быстрее, чем О(n) ?

DC>Поделись мудростью.

Если значений много и список нужно создать один раз, а обращаться к нему часто, то можно конечный автомат построить.
Иначе — не заморачиваться и делать с линейной сложностью.
Re[3]: Проверка, что строка равна одному из значений
От: bnk СССР http://unmanagedvisio.com/
Дата: 25.03.19 08:31
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>>>В реальности, в этом if гораздо больше условий. На питоне я бы написал это так:

LD>>>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?
_>>
_>>if (confirms_all_conditions(status)) // ...
_>>

LD>так а дальше что? в функции будет тот же самый большой if с кучей условий

1. Внутри функции можно переменную коротким именем назвать, типа "s" или "x"
2. Имя функции — бесплатный комментарий что там вообще происходит (в чем смысл условия)
3. Околонулевой оверхед
4. Не парим людям мозг на ровном месте, вводя сеты или initializer list

В общем, не жили хорошо — не стоит и начинать. Вот был бы нормальный "in" или switch — его и надо было бы использовать.
Re[2]: Проверка, что строка равна одному из значений
От: Sergey_BG Россия  
Дата: 25.03.19 09:26
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>в пайтон стиле:

X>
X>    if ( static const std::set<std::string> set{"1234", "4321"}; set.count("1234") ) {
X>        std::cout << 1 << std::endl;
X>    } else {
X>        std::cout << 0 << std::endl;
X>    }
X>


У меня не компилируется ни в VS2015, ни в идеоне
Да и страшно как-то выглядит. Объявляешь переменную. Статик. В ифе. Потом точка с запятой. А потом условие.
Сергей
Re[3]: Проверка, что строка равна одному из значений
От: B0FEE664  
Дата: 25.03.19 10:05
Оценка:
Здравствуйте, Sergey_BG, Вы писали:

S_B>У меня не компилируется ни в VS2015, ни в идеоне

S_B>Да и страшно как-то выглядит. Объявляешь переменную. Статик. В ифе. Потом точка с запятой. А потом условие.
Так можно писать начиная с C++17.
И каждый день — без права на ошибку...
Re[4]: Проверка, что строка равна одному из значений
От: _NN_ www.nemerleweb.com
Дата: 25.03.19 10:31
Оценка: -1
bnk>В общем, не жили хорошо — не стоит и начинать. Вот был бы нормальный "in" или switch — его и надо было бы использовать.
Есть ещё
std::ranges::all_of
https://en.cppreference.com/w/cpp/algorithm/ranges/all_any_none_of

Чего ещё нет в плюсах так это лёгкого создания списка но и это решаемо:
https://www.boost.org/doc/libs/1_52_0/libs/assign/doc/index.html#list_of

Итого:all_of(list_of(1)(2)(3), [](auto x){return x==1;})
Красиво и неэффективно

Увы нет синтаксиса попроще для лямбд пока.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Проверка, что строка равна одному из значений
От: Don Reba Канада https://stackoverflow.com/users/49329/don-reba
Дата: 25.03.19 22:07
Оценка:
Здравствуйте, Lonely Dog, Вы писали

LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


Если не хочется использовать ассоциативные контейнеры:

using namespace boost::algorithm;
using namespace std;
using namespace std::placeholders;

if (any_of(vector<string>{"1234", "2345", "3456"}, bind(equal_to<string>(), status, _1)))
    cout << "found it!\n";
Ce n'est que pour vous dire ce que je vous dis.
Отредактировано 25.03.2019 22:10 Don Reba . Предыдущая версия .
Re: Проверка, что строка равна одному из значений
От: SaZ  
Дата: 26.03.19 00:22
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Добрый день!


LD>Есть следующий код:

LD>
LD>if (status == "1234" ||
LD>    status == "2345" || 
LD>    status == "3456")
LD>{
LD> // do something
LD>}
LD>


LD>В реальности, в этом if гораздо больше условий. На питоне я бы написал это так:

LD>
LD>if status in ["1234", "2345", "3456"]:
LD>  # do something
LD>


LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


Если строки известны в момент компиляции, то можно написать длинный свитч
Автор: niXman
Дата: 30.03.17
с одним break; в конце.
Re: Проверка, что строка равна одному из значений
От: andrey.desman  
Дата: 26.03.19 00:32
Оценка: 45 (8)
Здравствуйте, Lonely Dog, Вы писали:

LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


template<typename T, typename... Args>
constexpr bool is_any_of(T&& v, Args&&... args)
{
    return ((v == args) || ...);
}

int main(int argc, char* argv[])
{
    using namespace std::literals;
    std::string a = "123"s;
    std::string b = "234"s;
    std::cout << is_any_of(a, b, "123"sv) << '\n';

    return 0;
}
Re[5]: Проверка, что строка равна одному из значений
От: SuhanovSergey  
Дата: 26.03.19 08:30
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>Здравствуйте, niXman, Вы писали:


X>> линейная сложность.


DC>А что, это можно сделать быстрее, чем О(n) ?

DC>Поделись мудростью.

С помощью trie можно за время, пропорциональное длине проверяемой строки, и не зависящее от n (количества строк-условий). Конечно, это требует препроцессинга, как и с set.
Re: Проверка, что строка равна одному из значений
От: Skorodum Россия  
Дата: 26.03.19 11:40
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


std::any_of
Re: Проверка, что строка равна одному из значений
От: Basil2 Россия https://starostin.msk.ru
Дата: 28.03.19 12:43
Оценка:
Здравствуйте, Lonely Dog, Вы писали:

LD>Есть следующий код:

LD>
LD>if (status == "1234" ||
LD>    status == "2345" || 
LD>    status == "3456")
LD>{
LD> // do something
LD>}
LD>


LD>А можно ли что-нибудь такое написать на C++, как-нибудь сократить код?


Да:

static const std::set<std::string> validStatuses { "1234", "2345", "3456" };
if (validStatuses.count(status) > 0)
{
  // do something
}


Можно в одну строку внутри if (как уже приводили ранее), но будет смотреться странно. Для пущей красоты можно оформить "count() > 0" как отдельную функцию, но так же будет смущать читателей.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Re: Проверка, что строка равна одному из значений
От: RussianFellow Россия http://russianfellow.livejournal.com
Дата: 01.04.19 09:46
Оценка: :)))
Здравствуйте, Lonely Dog, Вы писали:

LD>Добрый день!


LD>Есть следующий код:

LD>
LD>if (status == "1234" ||
LD>    status == "2345" || 
LD>    status == "3456")
LD>{
LD> // do something
LD>}
LD>


Правильно писать:

if ((strcmp(status,"1234")==0)||
(strcmp(status,"2345")==0)||
(strcmp(status,"3456")==0))
{
// do something
}

Потому что в C/C++ строковая переменная представляет собой указатель на самый первый (нулевой) элемент строки. И поэтому для сравнения строк надо пользоваться не = , а функцией strcmp, которая возвращает 0 в случае равенства и ненулевое значение в случае неравенства.
1613 г. = 2024 г.
Re[2]: Проверка, что строка равна одному из значений
От: AleksandrN Россия  
Дата: 01.04.19 09:58
Оценка:
Здравствуйте, RussianFellow, Вы писали:

RF>Правильно писать:


RF>if ((strcmp(status,"1234")==0)||

RF> (strcmp(status,"2345")==0)||
RF> (strcmp(status,"3456")==0))
RF>{
RF> // do something
RF>}

RF>Потому что в C/C++ строковая переменная представляет собой указатель на самый первый (нулевой) элемент строки. И поэтому для сравнения строк надо пользоваться не = , а функцией strcmp, которая возвращает 0 в случае равенства и ненулевое значение в случае неравенства.


В С++ есть класс std::string, и перегруженный operator==(). Если тип status — std::string, то сравнение status == "1234" сравнивает строки. А strcmp нужно использовать для типов char* или char[].
Отредактировано 01.04.2019 9:59 AleksandrN . Предыдущая версия .
Re[6]: Проверка, что строка равна одному из значений
От: N. I.  
Дата: 03.04.19 14:14
Оценка: +1
niXman:

LD>>... создание hash_set (или еще чего-нибудь) займет явно больше времени, чем простой проход по этому списку.

X>посмотрите мой пример, в нем set будет инициализирован только один раз.

Зато поиск у std::set не особо-то быстрый. Хаотичное хождение по нодам set-а может быть заметно дороже, чем обход элементов компактного массива, т.к. данные из небольшой непрерывной области памяти легче кэшируются. Поэтому для каких-нибудь небольших наборов строк алгоритм с линейной сложностью вполне мог бы показать заметно лучшую производительность.
Re[3]: Проверка, что строка равна одному из значений
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.04.19 06:38
Оценка:
Здравствуйте, AleksandrN, Вы писали:

AN>А strcmp нужно использовать для типов char* или char[].


Сдается мне, с char[] могут быть траблы...

const char c[]={'a','b'};


В массиве будет строго два элемента. Без терминального нулевого символа.

Я все правильно напутал?
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Проверка, что строка равна одному из значений
От: Sergey_BG Россия  
Дата: 06.04.19 20:03
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>В массиве будет строго два элемента. Без терминального нулевого символа.
Да. Но можно инициализировать строкой "ab". В этом случае длина массива будет 3 символа.
Сергей
Re[5]: Проверка, что строка равна одному из значений
От: Erop Россия  
Дата: 17.04.19 14:07
Оценка:
Здравствуйте, DenisCh, Вы писали:

DC>А что, это можно сделать быстрее, чем О(n) ?

DC>Поделись мудростью.

Не знаю что тут за n, но поиск в боре, например, будет иметь другие асимптотики по сложности...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Проверка, что строка равна одному из значений
От: AleksandrN Россия  
Дата: 18.04.19 09:49
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Здравствуйте, AleksandrN, Вы писали:


AN>>А strcmp нужно использовать для типов char* или char[].


КД>Сдается мне, с char[] могут быть траблы...


КД>
КД>const char c[]={'a','b'};
КД>


КД>В массиве будет строго два элемента. Без терминального нулевого символа.


КД>Я все правильно напутал?


Траблы могут быть везде. Си не мешает стрелять себе в ногу. Можно и в char* записать строку без 0-символа в конце. Разработчик должен понимать, что он делает, как строки инициализировать и что использовать для сравнения, strcmp(), strncmp() или свой велосипед. Но все разработчики ошибаются.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.