๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
C++ ๊ธฐ์ดˆ

[C/C++] 8. ๋ฐ˜๋ณต๋ฌธ(์‹ฌํ™”)(feat. iterator, predicate, lambda)

by ์„œ์•„๋ž‘๐Ÿ˜ 2023. 4. 22.

 

 

์—ฌ๊ธฐ์„œ๋Š” C++์˜ Standard library ์ปจํ…Œ์ด๋„ˆ์˜ ์กฐ๊ฑด ์ˆœํšŒ์— ๋Œ€ํ•œ ๊ฐœ๋…๋“ค์„ ์ด์•ผ๊ธฐํ•œ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ€๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ์ฐธ๊ณ ํ•ด๋ณด๋„๋ก ํ•˜์ž.

 

bool NewsScheduler::checkSchedule(Schedule& schedule)
{
    const auto &curMilli = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count();
    const auto itr = find_if(scheduleMap.rbegin(), scheduleMap.rend(), [&curMilli](const pair<int, Schedule> &p)
                             { return p.second.start < curMilli && p.second.end > curMilli; });

    if ( itr == scheduleMap.rend())
        return true;

    schedule = itr->second;
    return true;
}
// scheduleMap : std::map<int, Schedule>

 

 

๊ฐ€์žฅ ์ตœ๊ทผ์— ๋“ฑ๋ก๋œ ์Šค์ผ€์ค„์˜ ์‹œ๊ฐ„์ด ๋˜๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

 

 

 

โœ… iterator, ๋ฐ˜๋ณต์ž

  C++์ด๋‚˜ ์ž๋ฐ”๋ฅผ ์‚ฌ์šฉํ•ด๋ณธ ์‚ฌ๋žŒ์ด๋ผ๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๋Š” ์ปจํ…Œ์ด๋„ˆ์˜ ์ข…๋ฅ˜๋Š” ๊ทธ ๊ตฌ์กฐ์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ๊ฐœ๋กœ ๋‚˜๋‰œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ vector(List)์™€ map(Hashmap)์ด ์žˆ๋‹ค. C++์˜ Standard library์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ iterator๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค. ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๋ฉ”๋ชจ๋ฆฌ์ƒ์— ์—ฐ์†์ ์ธ์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์™€ ๋น„์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ๋กœ ๋‚˜๋‰œ๋‹ค. ์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์ธ Array์˜ ๊ฒฝ์šฐ ์ธ๋ฑ์Šค๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ Array์˜ ๊ฐ’์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋‚˜, ๋น„์„ ํ˜• ์ž๋ฃŒ๊ตฌ์กฐ์ธ Map(Dictionary)์˜ ๊ฒฝ์šฐ๋Š” key๊ฐ’์„ ์•Œ์•„์•ผ value์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. ์ธ๋ฑ์Šค๋กœ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ์‹ ๋˜ํ•œ Out of bound๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Standard library(์ค„์—ฌ์„œ std)์—์„œ๋Š” iterator๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœํšŒํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

  iterator๋Š” begin()๊ณผ end()๋ฅผ ๊ฐ€์ง€๋ฉฐ ํฌ์ธํ„ฐ์ฒ˜๋Ÿผ ์ปจํ…Œ์ด๋„ˆ์˜ ์ฃผ์†Œ๋ฅผ ์ฐธ์กฐํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  read-only์™€ write ๋ฐ˜๋ณต์ž, ์ˆœ๋ฐฉํ–ฅ, ์—ญ๋ฐฉํ–ฅ ๋ฐ˜๋ณต์ž๋ฅผ ๋ชจ๋‘ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ์ž๋Š” ๋ฐ˜๋ณต์ž๋ฅผ ํ†ตํ•ด ์†์‰ฝ๊ฒŒ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

โœ… lambda ํ•จ์ˆ˜

๋žŒ๋‹ค ํ•จ์ˆ˜๋Š” ์ต๋ช…ํ•จ์ˆ˜๋ผ๊ณ ๋„ ๋ถˆ๋ฆฌ๋Š” ๋ฐ, ํ•จ์ˆ˜์˜ ๋ฏธ๋‹ˆ ๋ฒ„์ „ ์ฒ˜๋Ÿผ ์Šค์ฝ”ํ”„ ๋‚ด์—์„œ ์ •์˜ํ•˜๊ณ  ํ•„์š”ํ•ด ์˜ํ•ด ๋ฐ”๋กœ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.  ๋žŒ๋‹ค ํ•จ์ˆ˜์˜ ์‚ฌ์šฉ๋ฒ•์€ 2021.03.09 - [๊ฐœ๋ฐœ์Šคํƒ/C&C++] - [c++] ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์ •๋ฆฌ ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด ๋œ๋‹ค. 

 

 

 

โœ… Predicate, ์„œ์ˆ ์ž

  ๊ธฐ๋ณธ์ ์ธ ๊ฐœ๋…์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. A predicate is a statement (or function) that returns either true or false.

You pass some data into the predicate. The predicate logic then performs a check on the data. Then the function/statement return a true or false result to the caller.

  ์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ํ•œ๊ฐœ ์ด์ƒ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„์„œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๊ณ  boolean๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ Predicate๋ผ๊ณ  ํ•œ๋‹ค. ํ•œ๊ตญ์–ด๋กœ ํ•˜๋ฉด '์„œ์ˆ ์ž' ์ •๋„๊ฐ€ ๋˜๊ฒ ๋‹ค. 

 

 

 

 

โœ… std ์ปจํ…Œ์ด๋„ˆ ์กฐ๊ฑด ์ˆœํšŒ(find_if, count_if, remove_if)

  find, count์˜ ๊ฒฝ์šฐ 3๊ฐœ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ฐ›์•„ ์‹œ์ž‘ iterator, ๋ iterator, ์‹ค์ œ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋ฉด ๋ฒ”์œ„ ๋‚ด์— ํ•ด๋‹น ํ•˜๋Š” ๊ฐ’์˜ iterator๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค. ๋งŒ์•ฝ ์ฐพ์ง€ ๋ชปํ•œ๋‹ค๋ฉด end()๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );

 

find_if์™€ count_if, remove_if์˜ ๊ฒฝ์šฐ์—๋Š” 3๋ฒˆ์งธ ์ธ์ž๋กœ Predicate ํ•จ์ˆ˜๋ฅผ ๋„ฃ์œผ๋ผ๊ณ  ์ •์˜๋˜์–ด ์žˆ๋‹ค. ์ฆ‰, true/false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์กฐ๊ฑด์‹์„ returnํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ๊ทธ ์กฐ๊ฑด์‹์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•œ๋‹ค. UnarayPredicate๋Š” ๋‹จํ•ญ ์„œ์ˆ ์ž์ธ๋ฐ bool๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ณดํ†ต์˜ predicate์ด๋‹ค.

template< class InputIt, class UnaryPredicate >
InputIt find_if( InputIt first, InputIt last, UnaryPredicate p );

 

 

 

โœ… ์˜ˆ์ œ ์„ค๋ช…

const auto itr = find_if(scheduleMap.rbegin(), scheduleMap.rend(), [&curMilli](const pair<int, Schedule> &p)
                             { return p.second.start < curMilli && p.second.end > curMilli; });

 

std::find_if๋ฅผ ์‚ฌ์šฉํ•ด์„œ scheduleMap์˜ ๋งจ ๋’ค๋ถ€ํ„ฐ ๋งจ ์•ž๊นŒ์ง€ ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ–ˆ๋‹ค(์ฒซ ๋ฒˆ์งธ, ๋‘ ๋ฒˆ์งธ ์ธ์ž). rbegin, rend๋Š” reverse_iterator๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ ์—ญ๋ฐฉํ–ฅ ๋ฐ˜๋ณต์ž๋ฅผ ๋œปํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„ธ ๋ฒˆ์งธ ์ธ์ž๋กœ lambda ํ•จ์ˆ˜๋ฅผ ๋„ฃ์—ˆ๋‹ค. lambda ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” scheduleMap์˜ ๋‹จ์ผ ์›์†Œ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ–์ถฐ์•ผ ํ•˜๋Š” ๋ฐ, map์˜ ๋‹จ์ผ ์›์†Œ๋Š” pair์ด๊ธฐ ๋•Œ๋ฌธ์— const pair<int, Schedule>๊ณผ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ง€์ •ํ•œ๋‹ค. ๋žŒ๋‹ค ํ•จ์ˆ˜ ๋‚ด๋ถ€๋Š” ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ์กฐ๊ฑด์„ ๋„ฃ๊ณ  returnํ•œ๋‹ค. return๋ฌธ์€ ๋ฐ˜๋“œ์‹œ boolean ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค(Predicate). ์กฐ๊ธˆ ํ’€์–ด ์“ด๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ธ๋‹ค.

 

auto lambda_predicate = [&curMilli](const pair<int, Schedule> &p)
                             { return p.second.start < curMilli && p.second.end > curMilli; });

const auto itr = find_if(scheduleMap.rbegin(), scheduleMap.rend(), lambda_predicate);

 

๊ตณ์ด ๋žŒ๋‹ค ํ•จ์ˆ˜๋ฅผ ์“ฐ์ง€ ์•Š๊ณ  std::function์„ ์“ฐ๊ฑฐ๋‚˜ ์‹ค์ œ ํ•จ์ˆ˜์˜ ์ฃผ์†Œ๋ฅผ ๋„ฃ์–ด๋„ ๋œ๋‹ค. ํ•˜์ง€๋งŒ ์ต๋ช… ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๊ทธ์ž๋ฆฌ์—์„œ ์ •์˜ํ•˜๊ณ  ๋Œ€์ž…ํ•˜๋Š” ํŽธ์ด ํ›จ์”ฌ ํŽธํ•˜๋‹ค.

 

 

  ๊ทธ๋ฆฌ๊ณ , ๋žŒ๋‹ค ํ•จ์ˆ˜์˜ ์กฐ๊ฑด์‹์— ํ•ด๋‹นํ•˜๋Š” iterator๊ฐ€ itr๋ณ€์ˆ˜์— ๋‹ด๊ฒจ์ ธ ๋‚˜์˜จ๋‹ค. count_if๋Š” itrerator๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  int๋ฅผ ๋ฐ˜ํ™˜ ํ•˜๋Š”๋ฐ, ์กฐ๊ฑด์‹์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ๊ฐœ์ˆ˜๋งŒํผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. find_if๊ฐ€ ๋ฐ˜ํ™˜ํ•œ iterator๋กœ scheduleMap.end()์™€ ๋น„๊ตํ•˜๋ฉด์„œ ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด return false, ์žˆ์œผ๋ฉด call by reference๋กœ ๋„˜์–ด์˜จ schedule์— ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ  return true๋ฅผ ํ•œ๋‹ค.

 

 

 

  ์‚ดํŽด๋ณธ ์˜ˆ์ œ๋Š” ๊ฐ„๋‹จํ•œ ํ•จ์ˆ˜์ด๋ฉฐ ์‹ค๋ฌด์—์„œ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๋งŽ์ด ์“ฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ์†Œ๊ฐœํ–ˆ๋‹ค. ์งง์€ ํ•จ์ˆ˜์ง€๋งŒ Predicate, Lambda, Iterator์˜ ๊ฐœ๋…์ด ๋“ค์–ด๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์งš๊ณ  ๋„˜์–ด๊ฐˆ๋งŒ ํ•˜๋‹ค.

๋Œ“๊ธ€