3

C ++のリスト内の連続するゼロの実行ごとに、それらxを除く実行中のすべてのゼロを削除したいと思いxます。の場合x = 0、すべてゼロを削除します。

list<int> Lリストと数値int xを入力として受け取るC++関数を考えていました。

たとえば、L = {7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8}

  • の場合x = 0L = {7, 12, 2, 27, 10, 8}
  • の場合x = 1L = {7, 0, 12, 0, 2, 0, 27, 10, 0, 8}
  • の場合x = 2L = {7, 0, 12, 0, 0, 2, 0, 0, 27, 10, 0, 0, 8}
  • の場合x = 3L = {7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 8}
  • の場合x = 4、戻りL = {7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8}ます(元の値と同じL
  • の場合、 5つ以上の連続するゼロの実行がないため、x >= 5元の値を返します。L

数ヶ月前、私はPython( stackoverflow.com/questions/11732554 / ... )を使用して上記と同じ質問をし、優れた回答を受け取りました。ここで、このタスクをC++で完了したいと思います。

どんな助けでも心から感謝します。

4

6 に答える 6

5

これがその仕事をするべきいくつかのコードです:

void DeleteAllZerosInARow(std::list<int>& theList, int x)
{
    if(x == 0)
    {
        theList.remove(0);
        return;
    }

    int streak = 0;
    std::list<int>::iterator itor = theList.begin();
    while(itor != theList.end())
    {
        if(*itor == 0)
            ++streak;
        else
            streak = 0;

        if(streak > x)
            itor = theList.erase(itor);
        else
            ++itor;
    }
}

基本的に、行にあるゼロの数を数え、ゼロの場合はそれらを削除します。> xそれ以外の場合は、リストの反復を続けます。

次の出力を提供します。

  • 0:7,12,2,27,10,8
  • 1:7,0,12,0,2,0,27,10,0,8
  • 2:7,0,12,0,0,2,0,0,27,10,0,0,8
  • 3:7,0,12,0,0,2,0,0,0,27,10,0,0,0,8
  • 4:7,0,12,0,0,2,0,0,0,27,10,0,0,0,0,8
  • 5:7,0,12,0,0,2,0,0,0,27,10,0,0,0,0,8

それはあなたのスタイルに依存し、それを行うためremove_ifのより厄介な方法かもしれませんがC++、値を直接操作する方が明確であり、新しいデータ型(遭遇しstructた数を追跡するため)は含まれていません。0

を使用してコードが機能しない理由は、、、、および大きな数の間にNTL::ZZ暗黙の変換がないため、それができないためです。しかし、あなたができることは、次のようなものかもしれません。int0NTL::ZZremove(0)

if(x == 0)
{
    static ZZ zero; // default value is 0, static so that it is only constructed once
    theList.remove(zero); // remove all items who are equal to "zero"
    return;
}
于 2013-01-15T19:08:22.830 に答える
1

ケース0の場合はを使用できstd::remove、ケース1の場合std::uniqueはそれをにのみ適用する述語で使用できます0。より大きな値については、使用する卑劣なステートフル述語を考案するか、uniqueそのロジックを借用してより大きなシーケンスに適用します。

于 2013-01-15T19:03:04.947 に答える
1

最も簡単な方法は、を返してstd::vector<int>使用push_backすることです。これにより、適切なサイズの配列を割り当てることを心配する必要がなくなります。

template<typename Iter>
std::vector<int> filter_zeroes(Iter start, Iter end, const size_t num_zeroes)
{
    std::vector<int> output;
    size_t zero_count = 0;
    while (start != end)
    {
        if (*start != 0)
        {
            output.push_back(*start);
            zero_count = 0;
        }
        else if (zero_count < num_zeroes)
        {
            output.push_back(*start);
            ++zero_count;
        }
        ++start;
    }
}

このメソッドをもっと一般的にすることができます。に変更intするtypename ValueType0、一般性のレベルに向かっValueType value_to_removeています...std::algorithm

于 2013-01-15T19:08:25.077 に答える
0

ファンクターをlist::remove_ifに渡すことで実行できます。以下の例。

#include <iostream>
#include <list>

std::list<int> origL{7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8};

template <typename T>
struct remove_more_than_n_consecutive_zeros
{
    int n;
    int i;
    F(int n) : n(n), i(0) { }

    bool operator()(const T &element) {
        if (0 == element) {
            ++i;
            return i > n;
        }
        else 
        {
            i = 0;
            return false;
        }
    }
};

int main()
{
    for (int i = 0; i < 5; ++i) {
        std::list<int> L = origL;
        L.remove_if(remove_more_than_n_consecutive_zeros<int>(i));
        for (int x : L) { std::cout << x << " "; }
        std::cout << std::endl;
    }
}
于 2013-01-15T19:12:19.567 に答える
0

これは本質的にステートマシンであるため、std :: regexを使用して何か賢いことを行うことができますが、ここでは簡単な実装を示します。

void TrimConsecutiveValues(int value, int cKeep, std::list<int> &list) {
  int cSeen = 0;
  auto it = list.begin();
  while (it != list.end()) {
    if (*it == value) {
      if (cSeen < cKeep) {
        ++cSeen;
        ++it;
      } else {
        it = list.erase(it);
      }
    } else {
      cSeen = 0;
      ++it;
    }
  }
}
于 2013-01-15T19:20:37.380 に答える
0

これは、任意の型に使用するC ++ 11バージョン(auto、ラムダ、および移動セマンティクスを使用)です。std::vectorvalueT

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>

template<std::size_t N, typename T>
std::vector<T> collapse_consecutive(std::vector<T> v, T const& value)
{
    if (v.size() <= N) return v;

    for (auto it = v.begin(); it != std::prev(v.end(), N); ++it) {
        if (*it == value) {
            // find first following mismatch
            auto jt = std::find_if(it, v.end(), [&](T const& elem) {               
               return elem != value;
            });
            // keep first N matches, remove rest of matches
            if (std::distance(std::next(it, N), jt) > 0)               
                v.erase(std::remove(std::next(it, N), jt, value), jt);
        }
    }
    std::for_each(v.begin(), v.end(), [](int const& elem) { std::cout << elem << ", "; });
    std::cout << "\n";
    return v;
}

int main()
{
   std::vector<int> v = {7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8};

  collapse_consecutive<0>(v, 0);
  collapse_consecutive<1>(v, 0);
  collapse_consecutive<2>(v, 0);
  collapse_consecutive<3>(v, 0);
  collapse_consecutive<4>(v, 0);
  collapse_consecutive<5>(v, 0);  
}

LiveWorkSpaceでの出力

stdout: 
7, 12, 2, 27, 10, 8, 
7, 0, 12, 0, 2, 0, 27, 10, 0, 8, 
7, 0, 12, 0, 0, 2, 0, 0, 27, 10, 0, 0, 8, 
7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 8, 
7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8, 
7, 0, 12, 0, 0, 2, 0, 0, 0, 27, 10, 0, 0, 0, 0, 8, 
于 2013-01-15T20:03:45.287 に答える