it-swarm.dev

استخدام الأمراض المنقولة جنسيا :: ملء لملء ناقلات بأعداد متزايدة

أرغب في ملء vector<int> باستخدام std::fill ، ولكن بدلاً من قيمة واحدة ، يجب أن يحتوي المتجه على أرقام بترتيب متزايد بعد ذلك.

لقد حاولت تحقيق ذلك عن طريق تكرار المعلمة الثالثة للوظيفة بواحد ، لكن هذا من شأنه أن يمنحني فقط أي متجهات مملوءة بواحد أو اثنين (حسب موقع مشغل ++).

مثال:

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
56
BlackMamba

يفضل استخدام 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.
91
BoBTFish

يجب عليك استخدام خوارزمية 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::iota هي خوارزمية C++ 11 STL. لكن الكثير من المترجمين المعاصرين يدعمونها على سبيل المثال GCC و Clang و VS2012: http://msdn.Microsoft.com/en-us/library/vstudio/jj651033.aspx

30
Oleksandr Karaberov

سيكون خياري الأول (حتى في الإصدار 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 من counting_iterator لإنشاء جميع أنواع التسلسلات المثيرة للاهتمام. بدون Boost ، يمكنك القيام بالكثير من هذا باليد ، إما في شكل نوع كائن مولد لـ std::generate ، أو كشيء يمكنك سد العجز في يد مكتوبة العد التكرار.)

10
James Kanze

إذا كنت تفضل عدم استخدام ميزات 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.

6
Frerich Raabe

الأمراض المنقولة جنسيا :: 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);

لكنني لا أوصي به. :)

4
pururu

لقد رأيت الإجابات مع std :: إنشاء ، لكن يمكنك أيضًا "تحسين" ذلك باستخدام المتغيرات الثابتة داخل لامدا ، بدلاً من إعلان عداد خارج الوظيفة أو إنشاء فئة مولد:

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

أجدها أكثر إيجازًا قليلاً

4
brainsandwich

هذا يعمل ايضا

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

يمكننا استخدام توليد وظيفة موجودة في ملف رأس الخوارزمية.

مقتطف الشفرة:

#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;
}
2
rashedcs

إذا كنت بالفعل تريد استخدام 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;
}
1
King Kokonut

لقد أنشأت وظيفة بسيطة تم إنشاؤها ، Sequence() ، لإنشاء سلسلة من الأرقام. تتبع الوظيفة seq() في R ( link ). الشيء الجميل في هذه الوظيفة هو أنها تعمل على توليد مجموعة متنوعة من تسلسل الأرقام وأنواعها.

#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;
}

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

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

التحذير الوحيد هو أن جميع الأرقام يجب أن تكون من نفس النوع المستنتج. بمعنى آخر ، بالنسبة إلى الزوجي أو العائم ، قم بتضمين الكسور العشرية لجميع المدخلات ، كما هو موضح.

تم التحديث: 14 يونيو 2018

0
Adam Erickson

يتحدث عن دفعة:

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

أعلم أن هذا سؤال قديم ، لكنني ألعب حاليًا مع library للتعامل مع هذه المشكلة بالضبط. يتطلب ج ++ 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, ...
0
Dawid