2016-12-12 9 views
1

Я пытаюсь сделать увеличивающий вектор с помощью transform и не должен делать это правильно. Я хочу использовать преобразование. Что я делаю не так?Использование `transform` для создания возрастающего вектора

PS - Я буду использовать стандарт C++ 11 и g ++.

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

int main() 
{ 
    std::vector<double> x(10); 
    x.front() = 0.0; 
    double h = 0.1; 
    std::transform(x.begin(), x.end() - 1, x.begin() + 1, [h](unsigned int xn) {return xn + h;}); 
    std::cout << x.at(3) << " " << x.at(9) << std::endl; 
} 
+1

'[h] (unsigned int xn)' -> '[h] (double xn)' – jpw

+0

Вы хотите, чтобы изменить элементы? Или вы хотите добавить дополнительные преобразованные элементы? Или вы просто хотите заполнить вектор арифметической последовательностью? – Christophe

+3

Это выглядит как работа для 'std :: generate'. –

ответ

5

Преобразования в беззнаковый ИНТ усечение каждого значения, когда оно используется для вычисления следующего

+0

Rookie ошибка, мой плохой. Благодарю. – oliversm

+1

Это одна из причин, по которой всегда нужно использовать 'auto' при написании лямбда для функции :) – Rakete1111

+1

@ Rakete1111: Это поддерживается только с C++ 14, к сожалению. –

1

лямбды объявляет неправильный тип параметра

[h](unsigned int xn) {return xn + h;}); 
    ^^^^^^^^^^^^^^^ 

Там должен быть

[h](double xn) {return xn + h;}); 
    ^^^^^^^^^^^ 
1

Вот несколько других способов написать это. Вы можете найти их более выразительными.

#include <vector> 
#include <algorithm> 
#include <numeric> 

std::vector<double> create1(double i, double h) 
{ 
    std::vector<double> v(10); 
    std::generate(std::begin(v), std::end(v), 
       [&]() mutable 
    { 
    auto result = i; 
    i += h; 
    return i; 
    }); 
    return v; 
} 

std::vector<double> create2(double i, double h) 
{ 
    std::vector<double> v(10); 
    for (std::size_t x = 0 ; v.size() ; ++x) { 
    v[x] = i + h * x; 
    } 
    return v; 
} 

std::vector<double> create3(double i, double h) 
{ 
    struct emitter 
    { 
    emitter& operator++() { 
     i += h; 
    } 
    operator double() const { return i; } 
    double i, h; 
    }; 
    std::vector<double> v(10); 
    std::iota(v.begin(), v.end(), emitter { i, h }); 
    return v; 
} 

int main() 
{ 
    auto v1 = create1(0, 0.1); 
    auto v2 = create2(0, 0.1); 
    auto v3 = create3(0, 0.1); 
} 
2

std::transform - Использование унарный оператор

std::transform применяет данную функцию к диапазону и сохраняет результат в другом диапазоне, начиная с d_first.

Via std::transform и замыкание вы можете инициализировать std::vector:

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

int main() { 
    std::vector<double> v(10); 
    const double step = 0.1; 

    std::transform(begin(v), end(v), begin(v), 
       [step](const double value) { return value + step; }); 

    for (const auto value : v) { 
    std::cout << value << ' '; 
    } 
} 

std::generate - Приращение через отзывной

Назначает каждый элемент в диапазоне [первый, последний) значение генерируется данный функциональный объект

Если вы хотите пользовательский инкремент, вы можете использовать std::generate:

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

int main() { 
    std::vector<double> v(10); 
    double seed = 0.0; 

    std::generate(begin(v), end(v), [&seed]() { 
    const auto ret = seed; 
    seed += 0.1; 
    return ret; 
    }); 

    for (const auto value : v) { 
    std::cout << value << ' '; 
    } // outputs: 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 
} 

std::iota - Приращение через ++value

Немного не по теме. Вы можете указать тип с operator++ для приращения 0.1, но он не является интуитивным для читателя.

Вы можете использовать std::iota, который полагается на operator++.

Заполняет диапазон [первый, последний] с последовательно увеличивающимися значениями, начиная со значения и повторяя оценку ++value.

код в вашем случае будет:

#include <numeric> 
#include <iostream> 
#include <vector> 

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

    std::iota(begin(v), end(v), 0.0); 

    for (const auto value : v) { 
    std::cout << value << ' '; 
    } // outputs: 0 1 2 3 4 5 6 7 8 9 
} 
+0

Не знаю о 'iota'. Очень полезно. – oliversm

+0

это не приводит к требуемому выходу - он хочет увеличить на 0,1. Вам нужно сделать третий аргумент std :: iota - настраиваемый объект, который поддерживает 'operator ++' и' operator double'. –

+0

@RichardHodges true. Я редактирую свой ответ. – Lud

0

Независимо от каких-либо других проблем, которые она может иметь, ваша реализация имеет тонкий недостаток: он основывается на каждом предыдущем значении в векторе будучи уже установлен ,

Этого не гарантировано полагается, так как std::transform()does not guarantee in-order application of the operator.

 Смежные вопросы

  • Нет связанных вопросов^_^