Komma separierte optional Liste



  • Ich will eine Komma separierte Liste erzeugen, bei dem Array Elemente optional sind.

    std::vector <boost::optional <int>> vec = {boost::none, 2, 3, boost::none, 4, boost::none};
    
    std::stringstream sstr;
    createCommaList(sstr, vec); // -> 2, 3, 4
    

    Mir fällt gerade kein schöner code für ein.

    Probleme sind offensichtlich die Grenzfälle vorne und hinten.
    Ich habe immer ein dangling Komma am Ende oder Beginn.

    EDIT: Ich weiß nicht warum man sowas in einem array braucht, aber ich muss es unterstützen, aufgrund von Konventionen.



  • Mit einem bool flag first müsste das gehen. Weiß nicht, obs eine wirklich schöne Lösung ist, aber das schaut nach einem Dreizeiler aus und da würde ich auch nicht viel Aufwand in irgendwelche Spielereien reinstecken.



  • Immer wenn du einen Wert in der Liste anhängen willst, fügst du ", " davor (außer beim ersten Mal - kannst dafür ein boolsches Flag verwenden).



  • EDIT: moment.



  • So ich habe ne Lösung, die ist aber mehr als nur ein Dreizeiler.

    note: stringify schreibt die zahl auf den stream, oder nichts.
    is_optional_set(opt) gibt opt.operator bool() zurück, falls opt ein boost::optional ist, ansonsten gibt es true zurück und wird inlined.

    if (!values.empty())
    {
        stringify(stream, {}, *values.begin(), options);
        bool frontEmpty = !Internal::is_optional_set(*values.begin());
    
        for (auto i = values.begin() + 1; i < values.end(); ++i)
        {
            if (!frontEmpty && Internal::is_optional_set(*i))
                stream << options.delimiter;
            if (frontEmpty)
                frontEmpty = !Internal::is_optional_set(*i);
            stringify(stream, {}, *i, options);
        }
    }
    

    EDIT: Ich habe am Anfang nicht lange genug drüber nachgedacht. Ich musste erstmal raufinden, was ich überhaupt flaggen will.



  • bool first = true;
    for (const auto& v: values)
     if (v) {
       if (!first)
         stream << options.delimiter;
       stream << v;
       first = false;
     }
    

    Irgendsowas könnte ich mir vorstellen, ist evtl. teilweise Pseudocode 😃



  • edit: ok das geht auch und ist effizienter.

    So simpel... warum bin ich da nicht drauf gekommen? -.-

    EDIT: Wo bei es in der Essenz ja fast das gleiche ist. Nur mit ein paar Verbesserungen.



  • Dein Code macht wahrscheinlich das gleiche. Das einzige was mich etwas stört ist, dass es "mehr" Code ist und man länger über die Logik nachdenken muss. Es gibt mehr ifs, es gibt &&, es wird irgendwas vor der Schleife gemacht... Deswegen habe ich nochmal die simpelste Lösung hingeschrieben, die mir einfällt.



  • Aber je nachdem, wie viel Elemente ich schreiben muss, will ich doch nicht jedes Mal eine if-Abfrage in der Schleife haben:

    schreibe Element[0];
    
    for(int i = 1; i < Element.size(); ++i)
    {
       schreibe Separator;
       schreibe Element[i];
    }
    


  • Das berücksichtigt aber nicht das optional, weder bei dem ersten Element, noch bei den folgenden. Sonst würde man selbstverständlich kein if brauchen 😉



  • Wenn es kein Stream sein muss, sondern ein std::string oder vector<char> auch OK wäre, dann würde ich sagen: Einfache Schleife die "wert, komma" einfügt, und nach der Schleife das letzte Komma wieder wegtun.
    Das ist der einfachste Code der mir einfällt.

    Wenn das nicht geht, dann finde ich die akzeptierte Lösung der Frage
    http://stackoverflow.com/questions/4546021/remove-char-from-stringstream-and-append-some-data
    gut.

    Sylvain Defresne schrieb:

    std::ostringstream douCoh;
    const char* separator = "";
    
    douCoh << '{';
    for (size_t i = 0; i < dataSize; ++ i)
    {
      if (v[i].test)
      {
        douCoh << separator << i + 1;
        separator = ",";
      }
    }
    douCoh << '}';
    

    Bzw. ansonsten die Variante von Mechanics.
    Ist zwar im Prinzip das selbe, aber vermutlich für manche Programmierer einfacher zu verstehen.



  • Mechanics schrieb:

    Das berücksichtigt aber nicht das optional, weder bei dem ersten Element, noch bei den folgenden. Sonst würde man selbstverständlich kein if brauchen 😉

    Vielleicht hab ich das Problem nicht richtig verstanden ...
    " ... wobei Array Elemente optional sind ..."
    heißt doch nicht, dass der Separator optional ist? 😕



  • Belli schrieb:

    heißt doch nicht, dass der Separator optional ist? 😕

    Doch, sieht man ja in dem Beispiel im Kommentar, wie er das haben will.



  • @Belli
    Wollte auch erst die Lösung aus der von mir verlinkten Stack Overflow Frage "anpassen" damit sie immer die "," macht. Bis ich dann doch noch gesehen habe dass er die "," bei leeren Elementen gar nicht haben will. 🙂


Log in to reply