<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Variante von std::unique]]></title><description><![CDATA[<p>Hallo Forum,</p>
<p>std::unique sorgt ja dafür, dass aus jeder aufeinanderfolgenden Sequenz von gleichen Werten nur der erste erhalten bleibt.<br />
Aus</p>
<pre><code>{ 1, 2, 2, 3, 4, 4, 5, 6 };
</code></pre>
<p>wird</p>
<pre><code>{ 1, 2, 3, 4, 5, 6, ?, ? }
</code></pre>
<p>Ich würde gerne erreichen, dass die Sequenz so umsortiert wird, dass aufeinanderfolgende gleiche Werte ans Ende gestellt werden. Für obigen Fall also:</p>
<pre><code>{ 1, 3, 5, 6, 2, 2, 4, 4 };
</code></pre>
<p>Folgende erste Implementation habe ich mir dazu einfallen lassen:</p>
<p>- comp wäre eine Vergleichsfunktion wie für std::sort, standardmäßig std::less&lt;&gt;()<br />
- der zurückgegebene Iterator würde auf das erste Duplikat zeigen, also im obigen Fall auf die erste 2</p>
<pre><code>template&lt;typename RandomAccessIterator, typename Compare&gt;
   RandomAccessIterator RemoveDuplicates(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
   {
      if (first == last)
         return last;

      std::sort(first, last, comp); // (1) dürfte auch voraussgesetzt werden

      auto result = last;
      while (first != result)
      {
         auto upper = std::upper_bound(first, result, *first, comp); // finde nächstes unterschiedliches Element

         if (upper != std::next(first)) // nächstes Element ist gleich
         {
            std::rotate(first, upper, last); // Duplikate ans Ende der Range
            std::advance(result, -std::distance(first, upper)); // (2) result-iterator auf erstes Duplikat
         }
         else
            ++first;
      }

      return result;
   }
</code></pre>
<p>Prinzipiell erfüllt das nach ersten Tests seinen Zweck, so richtig rund wirkt es auf mich aber noch nicht. Zudem wäre es mir lieber, ich könnte anstatt der RandomAccessIterators ForwardIterators verwenden. Dann müsste das sort (siehe (1)) vorausgesetzt werden und die Positionierung des result-iterators (siehe (2)) müsste jedesmal erneut vom Beginn der Range erfolgen.</p>
<p>Sofern jemand Muße hat, wäre ich für ein wenig konstruktive Kritik dankbar!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/336918/variante-von-std-unique</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 20:35:30 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/336918.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 24 Feb 2016 11:52:05 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Variante von std::unique on Wed, 24 Feb 2016 11:52:05 GMT]]></title><description><![CDATA[<p>Hallo Forum,</p>
<p>std::unique sorgt ja dafür, dass aus jeder aufeinanderfolgenden Sequenz von gleichen Werten nur der erste erhalten bleibt.<br />
Aus</p>
<pre><code>{ 1, 2, 2, 3, 4, 4, 5, 6 };
</code></pre>
<p>wird</p>
<pre><code>{ 1, 2, 3, 4, 5, 6, ?, ? }
</code></pre>
<p>Ich würde gerne erreichen, dass die Sequenz so umsortiert wird, dass aufeinanderfolgende gleiche Werte ans Ende gestellt werden. Für obigen Fall also:</p>
<pre><code>{ 1, 3, 5, 6, 2, 2, 4, 4 };
</code></pre>
<p>Folgende erste Implementation habe ich mir dazu einfallen lassen:</p>
<p>- comp wäre eine Vergleichsfunktion wie für std::sort, standardmäßig std::less&lt;&gt;()<br />
- der zurückgegebene Iterator würde auf das erste Duplikat zeigen, also im obigen Fall auf die erste 2</p>
<pre><code>template&lt;typename RandomAccessIterator, typename Compare&gt;
   RandomAccessIterator RemoveDuplicates(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
   {
      if (first == last)
         return last;

      std::sort(first, last, comp); // (1) dürfte auch voraussgesetzt werden

      auto result = last;
      while (first != result)
      {
         auto upper = std::upper_bound(first, result, *first, comp); // finde nächstes unterschiedliches Element

         if (upper != std::next(first)) // nächstes Element ist gleich
         {
            std::rotate(first, upper, last); // Duplikate ans Ende der Range
            std::advance(result, -std::distance(first, upper)); // (2) result-iterator auf erstes Duplikat
         }
         else
            ++first;
      }

      return result;
   }
</code></pre>
<p>Prinzipiell erfüllt das nach ersten Tests seinen Zweck, so richtig rund wirkt es auf mich aber noch nicht. Zudem wäre es mir lieber, ich könnte anstatt der RandomAccessIterators ForwardIterators verwenden. Dann müsste das sort (siehe (1)) vorausgesetzt werden und die Positionierung des result-iterators (siehe (2)) müsste jedesmal erneut vom Beginn der Range erfolgen.</p>
<p>Sofern jemand Muße hat, wäre ich für ein wenig konstruktive Kritik dankbar!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2488451</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2488451</guid><dc:creator><![CDATA[DuplicateRemover]]></dc:creator><pubDate>Wed, 24 Feb 2016 11:52:05 GMT</pubDate></item><item><title><![CDATA[Reply to Variante von std::unique on Wed, 24 Feb 2016 15:27:36 GMT]]></title><description><![CDATA[<p>Deine Variante kann deinen Anforderungen entsprechend angepasst werden, indem Duplikate immer zum nächsten Duplikat rotiert werden, etc. die Anzahl der swaps ist dann linear, und wir brauchen lediglich Forward Iterators.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2488481</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2488481</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Wed, 24 Feb 2016 15:27:36 GMT</pubDate></item><item><title><![CDATA[Reply to Variante von std::unique on Thu, 25 Feb 2016 07:35:57 GMT]]></title><description><![CDATA[<p>Ich habe inzwischen eine Variante implementiert, die mit ForwardIterators auskommt. Es werden alle aufeinanderfolgenden gleichen (gemäß Vergleichsfunktion) Elemente ans Ende der Range verschoben. Will man also tatsächlich alle Duplikate entfernen, muss man vor Aufruf der Funktion sortieren (ähnlich wie bei std::unique).<br />
Einzig die Positionierung des result-Iterators gefällt mir noch nicht hundertprozentig, weil ich den nach jedem rotate durch Inkrementierung ausgehend von &quot;first&quot; neu positioniere und damit möglicherweise unnötig oft inkrementiere.</p>
<p>Deinen Vorschlag bezüglich der Rotation der Duplikate werde ich mir mal anschauen. Vielen Dank für die Anregung!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2488562</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2488562</guid><dc:creator><![CDATA[DuplicateRemover]]></dc:creator><pubDate>Thu, 25 Feb 2016 07:35:57 GMT</pubDate></item></channel></rss>