Nice programing

std :: fill을 사용하여 증가하는 숫자로 벡터 채우기

nicepro 2020. 11. 29. 12:17
반응형

std :: fill을 사용하여 증가하는 숫자로 벡터 채우기


vector<int>using 을 채우고 std::fill싶지만 하나의 값 대신 벡터에 숫자가 오름차순으로 포함되어야합니다.

함수의 세 번째 매개 변수를 하나씩 반복하여이를 달성하려고 시도했지만 이것은 1 또는 2로 채워진 벡터 만 제공합니다 ( ++연산자 의 위치에 따라 다름 ).

예:

vector<int> ivec;
int i = 0;
std::fill(ivec.begin(), ivec.end(), i++); // elements are set to 1
std::fill(ivec.begin(), ivec.end(), ++i); // elements are set to 2

다음 std::iota과 같이 사용하는 것이 좋습니다 .

std::vector<int> v(100) ; // vector with 100 ints.
std::iota (std::begin(v), std::end(v), 0); // Fill with 0, 1, ..., 99.

즉, c++11지원 이 없으면 (내가 일하는 곳에서 여전히 실제 문제) std::generate다음과 같이 사용 하십시오.

struct IncGenerator {
    int current_;
    IncGenerator (int start) : current_(start) {}
    int operator() () { return current_++; }
};

// ...

std::vector<int> v(100) ; // vector with 100 ints.
IncGenerator g (0);
std::generate( v.begin(), v.end(), g); // Fill with the result of calling g() repeatedly.

std::iota알고리즘 을 사용해야 합니다.

  std::vector<int> ivec;
  std::iota(ivec.begin(), ivec.end(), 0);

왜냐하면 std::fill단지 주어진 범위 [N1, N2)의 요소에 지정된 고정 값을 할당한다. 그리고 std::iota주어진 범위 [n1, n2)를 초기 값에서 시작하여를 사용하여 순차적으로 증가하는 값으로 채 웁니다 . 대안으로 ++value사용할 수도 있습니다 std::generate.

이것이 std::iotaC ++ 11 STL 알고리즘 임을 잊지 마십시오 . 그러나 GCC, Clang 및 VS2012와 같은 많은 최신 컴파일러가이를 지원합니다. http://msdn.microsoft.com/en-us/library/vstudio/jj651033.aspx


내 첫 번째 선택 (C ++ 11에서도)은 다음과 boost::counting_iterator같습니다.

std::vector<int> ivec( boost::counting_iterator<int>( 0 ),
                       boost::counting_iterator<int>( n ) );

또는 벡터가 이미 생성 된 경우 :

std::copy( boost::counting_iterator<int>( 0 ),
           boost::counting_iterator<int>( ivec.size() ),
           ivec.begin() );

Boost를 사용할 수 없다면 std::generate(다른 답변에서 제안한대로) 또는 counting_iterator필요한 경우 다양한 장소에서 직접 구현 하십시오. (Boost를 사용하면 transform_iterator의 a counting_iterator를 사용하여 모든 종류의 흥미로운 시퀀스를 만들 수 있습니다 . Boost가 없으면에 대한 생성기 객체 유형의 형태로 std::generate또는에 연결할 수있는 것으로이 많은 작업을 수작업 으로 수행 할 수 있습니다. 손으로 쓴 계산 반복자.)


C ++ 11 기능을 사용하지 않으려면 다음을 사용할 수 있습니다 std::generate.

#include <algorithm>
#include <iostream>
#include <vector>

struct Generator {
    Generator() : m_value( 0 ) { }
    int operator()() { return m_value++; }
    int m_value;
};

int main()
{
    std::vector<int> ivec( 10 );

    std::generate( ivec.begin(), ivec.end(), Generator() );

    std::vector<int>::const_iterator it, end = ivec.end();
    for ( it = ivec.begin(); it != end; ++it ) {
        std::cout << *it << std::endl;
    }
}

이 프로그램은 0에서 9까지 인쇄합니다.


std :: generate로 답변을 보았지만 함수 외부에서 카운터를 선언하거나 생성기 클래스를 만드는 대신 람다 내부에서 정적 변수를 사용하여 "개선"할 수도 있습니다.

std::vector<int> vec;
std::generate(vec.begin(), vec.end(), [] {
    static int i = 0;
    return i++;
});

좀 더 간결하다고 생각합니다


알고리즘 헤더 파일에 존재 하는 생성 기능을 사용할 수 있습니다 .

코드 스 니펫 :

#include<bits/stdc++.h>
using namespace std;


int main()
{
    ios::sync_with_stdio(false);

    vector<int>v(10);

    int n=0;

    generate(v.begin(), v.end(), [&n] { return n++;});

    for(auto item : v)
    {
      cout<<item<<" ";
    }
    cout<<endl;

    return 0;
}

std :: iota는 시퀀스 n, n + 1, n + 2, ...로 제한됩니다.

하지만 일반적인 시퀀스 f (0), f (1), f (2) 등으로 배열을 채우려면 어떻게해야할까요? 종종 상태 추적 생성기를 피할 수 있습니다. 예를 들면

int a[7];
auto f = [](int x) { return x*x; };
transform(a, a+7, a, [a, f](int &x) {return f(&x - a);});

일련의 사각형을 생성합니다.

0 1 4 9 16 25 36

그러나이 트릭은 다른 컨테이너에서는 작동하지 않습니다.

C ++ 98을 고수한다면 다음과 같은 끔찍한 일을 할 수 있습니다.

int f(int &x) { int y = (int) (long) &x / sizeof(int); return y*y; }

그리고

int a[7];
transform((int *) 0, ((int *) 0) + 7, a, f);

그러나 나는 그것을 추천하지 않을 것입니다. :)


이것은 또한 작동합니다

j=0;
for(std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it){
    *it = j++;
}

당신이 경우 실제로 사용하려는 std::fill및 C ++ (98)에 국한된다 당신은 다음과 같은 것을 사용할 수 있습니다,

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

struct increasing {
    increasing(int start) : x(start) {}
    operator int () const { return x++; }
    mutable int x;
};

int main(int argc, char* argv[])
{
    using namespace std;

    vector<int> v(10);
    fill(v.begin(), v.end(), increasing(0));
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;
    return 0;
}

부스트에 대해 말하면 :

auto ivec = boost::copy_range<std::vector<int>>(boost::irange(5, 10));

나는 이것이 오래된 질문이라는 것을 알고 있지만 현재이 문제를 정확히 처리하기 위해 라이브러리가지고 놀고 있습니다. C ++ 14가 필요합니다.

#include "htl.hpp"

htl::Token _;

std::vector<int> vec = _[0, _, 100];
// or
for (auto const e: _[0, _, 100]) { ... }

// supports also custom steps
// _[0, _%3, 100] == 0, 4, 7, 10, ...

In terms of performance you should initialize the vector with use of reserve() combined with push_back() functions like in the example below:

const int numberOfElements = 10;

std::vector<int> data;
data.reserve(numberOfElements);

for(int i = 0; i < numberOfElements; i++)
    data.push_back(i);

All the std::fill, std::generate, etc. are operating on range of existing vector content, and, therefore the vector must be filled with some data earlier. Even doing the following: std::vector<int> data(10); creates a vector with all elements set to its default value (i.e. 0 in case of int).

The above code avoids to initialize vector content before filling it with the data you really want. Performance of this solution is well visible on large data sets.


I created a simple templated function, Sequence(), for generating sequences of numbers. The functionality follows the seq() function in R (link). The nice thing about this function is that it works for generating a variety of number sequences and types.

#include <iostream>
#include <vector>

template <typename T>
std::vector<T> Sequence(T min, T max, T by) {
  size_t n_elements = ((max - min) / by) + 1;
  std::vector<T> vec(n_elements);
  min -= by;
  for (size_t i = 0; i < vec.size(); ++i) {
    min += by;
    vec[i] = min;
  }
  return vec;
}

Example usage:

int main()
{
    auto vec = Sequence(0., 10., 0.5);
    for(auto &v : vec) {
        std::cout << v << std::endl;
    }
}

The only caveat is that all of the numbers should be of the same inferred type. In other words, for doubles or floats, include decimals for all of the inputs, as shown.

Updated: June 14, 2018

참고URL : https://stackoverflow.com/questions/17694579/use-stdfill-to-populate-vector-with-increasing-numbers

반응형