1

Does anyone know whether I can use something from STL instead of this code:

std::vector<string> v = {"1", "2", "3", "4", "5", "6"};
std::vector<int> result;
for (auto i = 0; i < v.size(); i += 2)
{
    int transformed = std::stoi(v[i]);
    transformed += std::stoi(v[i+1]);
    result.push_back(transformed);
}

result is then {3, 7, 11} at the end.

Can I adjust std::transform in some way?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
bladzio
  • 414
  • 3
  • 15
  • 4
    Note that `std::stoi(v[i+1])` isn't guaranteed safe by `i < v.size()` - you should really be testing `i+1 < v.size()` (or test that `v.size()` is even). – Toby Speight Nov 10 '15 at 16:43
  • Take a look at `std::adjacent_difference`. You can pass you own binary function. Still you intention is harder because you final array is half as short. – villasv Nov 10 '15 at 16:47
  • A `for` loop is an efficient, simple and readable solution. Note that your `auto i = 0;` is of type `int`, after that you perform [an unsigned comparison](http://stackoverflow.com/questions/17505164/using-auto-in-loops-c)... use `size_t i = 0;` instead. – BeyelerStudios Nov 10 '15 at 16:50
  • 1
    I think in this case you're better off with a for loop – bolov Nov 10 '15 at 16:51
  • 1
    If your initial data was on two different arrays, you could use a custom function on `std::inner_product`. – villasv Nov 10 '15 at 16:52

2 Answers2

0

The following approach uses boost::iranges, and it works, but honestly, I think it's ugly.

auto indices=boost::irange(0,int(v.size()/2));
std::for_each(indices.begin(),indices.end(),[&](unsigned index){result.push_back(stoi(v[2*index])+stoi(v[2*index+1]));});

Live example: http://coliru.stacked-crooked.com/a/dfd2775e996d96c6

SPMP
  • 1,181
  • 1
  • 9
  • 24
0

Firstly you cannot apply std::transform or similar STL functions on containers with different types like here we have vector of both string & int type. You need to have both either string or int to apply STL. Assuming both your vectors are of int type (forgive me for that but I m just showing how your operation can take place) :-

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
    vector<int> v {1,2,3,4,5,6};
    vector<int> result(v.size());
    int i=0;
    adjacent_difference (v.begin(), v.end(), result.begin(),[&i](int s1, int s2)
    {
        int sum=0;
        if (i%2==0)
        sum=s1+s2;
        ++i;
        return sum;
    });
    auto it = partition (result.begin(), result.end(), [](int x)
    {
        return (x!=0);
    });
    int pos=it-result.begin()-1;
    result.erase (it, result.end());
    result.erase (result.begin());
    result.resize(pos);
    for_each (result.begin(), result.end(), [](int x)
    {
        cout<<x<<' ';
    });
    return 0;
}

Output will be :-

3 7 11

Here std::adjacent_difference will calculate the adjacent sums according to the function I have provided. For i=0, 2, 4, 2n, it will calculate the sum, else it will return 0. However the first element is always copied as it is, hence here first element in result will be 1.

std::partition is used to separate non-zero numbers with 0 (just a logic, you can use yours) as for i=2n+1, 0 was returned to result. This return an iterator to the element which is the last in the partition condition (here the last non-zero number e after which 0 starts).

Now as we have separated 0 & non-zero numbers, we need to remove the undesired ones. Hence you get 2 erase functions: One to eliminate 0 & the other to eliminate 1 in the beginning. After removing we resize the result vector & iterate over it.

HOWEVER, according to your case, a for loop is the best !!!

DevInd
  • 1,645
  • 2
  • 11
  • 17