اسم STL لوظيفة البرمجة الوظيفية "الخريطة"

StackOverflow https://stackoverflow.com/questions/3580457

  •  01-10-2019
  •  | 
  •  

سؤال

أود أن أكون قادرًا على كتابة شيء مثل

char f(char);
vector<char> bar;
vector<char> foo = map(f, bar);

ال transform يبدو أن الوظيفة متشابهة ، لكنها لن تتولى تلقائيًا حجم المجموعة الناتجة.

هل كانت مفيدة؟

المحلول

يمكنك استخدام std::back_inserter في <iterator>, ، على الرغم من أن توفير الحجم في المقدمة أكثر كفاءة. فمثلا:

string str = "hello world!", result;
transform(str.begin(), str.end(), back_inserter(result), ::toupper);
// result == "HELLO WORLD!"

نصائح أخرى

تم طرح هذا السؤال قبل ساري المفعول مع معيار C ++ 11 ... في الوقت الحاضر لدينا std::transform() باعتبارها (قبيحة) ما يعادل البرمجة الوظيفية "خريطة". إليك كيفية استخدامه:

auto f(char) -> char; // or if you like: char f(char)
vector<char> bar;
vector<char> foo;
// ... initialize bar somehow ...
std::transform(bar.begin(), bar.end(), std::back_inserter(foo), f);

لجعل هذا العمل ، ستحتاج إلى الملاحظات التالية:

  1. لجعل المهمة فعالة ، map يجب أن ليس قم بعملك. بدلاً من ذلك ، يجب أن يحفظ وسيطاته في كائن مؤقت (في حالتك ، سيكون ذلك مثيلًا class map::result<char(*)(char), vector<char> >)
  2. هذه map::result يجب أن يكون مؤقتًا template <typename T> operator T تحويلات.
  3. عندما map::result تم تعيينه إلى أ std::vector<char>, ، هذا التحويل هو الوحيد القابل للتطبيق.
  4. في مشغل التحويل class map::result<char(*)(char), vector<char> >::operator vector<char> لديك نوع الإدخال ونوع الإرجاع ، ووظيفة التعيين. في هذه المرحلة ، يمكنك تحويل المدخلات بفعالية.

<edit>

شفرة

template<typename CONT, typename FUNC>
class mapresult {
    CONT const& in;
    FUNC f;
public:
    template<typename RESULT> RESULT to() const
    {
        RESULT out;
        for (auto const& e : in) { out.push_back(f(e)); }
        return out;
    }
    template<typename RESULT> operator RESULT() const
    {
        return this->to<RESULT>();
    }
    mapresult(CONT const& in, FUNC f) : in(in), f(std::move(f)) { }
};

template<typename CONT, typename FUNC>
auto map(CONT const& in, FUNC f) -> mapresult<CONT, FUNC>
{
    return mapresult<CONT, FUNC>(in, f);
}

استخدم مثل هذا:

using namespace std;
char foo(char c) { return c | ('A' ^ 'a'); }
std::string in = "Test";

int main(int argc, char* argv[])
{
    string out = map(in, &foo);
    cout << out << endl;

    char replace = 'e';
    cout << map(in, [replace](char c){return c == replace ? '?' : c; }).to<string>();
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top