Как добавить элементы в вектор вместе на основе информации из другого вектора - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть две векторные структуры, одна содержит коды и стоимость для каждой, а другая - просто заказы, которые содержат запрошенные коды и totalCost (подлежит вычислению)

векторные части (коды, стоимость);

векторные порядки (коды, totalCost); // totalCost установлен в 0;

, где вектор частей содержит что-то вроде ('A', 10, 'B', 20);

, где A и B - части, 10 - стоимость для A, 20 стоит для B.

, а вектор заказов содержит такие заказы, как A, B, C или просто A, B. Скажем, мы получаем заказ из частей A и B.

как нам go добавить эти два на основе стоимости от частей и сохранить результат в новом int, который мы будем использовать позже, чтобы добавить к векторной структуре заказов (totalCost).

Я пытался несколько часов, я думаю, что мне нужно использовать std :: transform и, возможно, std :: аккумулировать? просто не знаю, как соединить их вместе ...

Это то, что я написал до сих пор:

int totalCost;
for(auto i : customers){
    for(auto x : parts){
      totalCost = accumulate(i.partsList.begin(), i.partsList.end(), ???);
      //then need to store cost for each order for use later
}

Я также пытался:

void test(){
    int cost;
    for(unsigned i =0; i < customers.size(); i++){
        for(unsigned x=0; x < partsVec.size(); x++){
            for(unsigned z=0; z < customers.at(i).partsList.size(); z++){

                if(partsVec.at(x).code == customers.at(i).partsList.at(z)){
                    cost += partsVec.at(x).cost;
                    customers.at(i).cost= cost;
                }
            }
        }
    }
      for(auto i : customers){
        cout << i.cost<< endl;
    }
}

Это выводит это:

40 //this is correct.

80 //this is incorrect, needs to be 40 as both customers have ordered same parts!

Как вы можете видеть, это продолжает компрометировать, и я не могу найти способ остановить это.

, что я пытаюсь сделать, это получить общая стоимость всех деталей в partsList на основе информации из вектора деталей. В векторе клиентов есть еще один вектор символов, называемый partsList, поэтому я могу изменить totalCost каждого заказа на значение, полученное сверху, используя накопление или другой алгоритм

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Попробуйте что-то вроде этого:

struct Part
{
    char code;
    double cost;

    Part(char code, double cost)
        : code(code), cost(cost)
    {
    }
};

std::vector<Part> parts;

double costOfPart(char code)
{
    for(const Part &part : parts)
    {
        if (part.code == code)
            return part.cost;
    }
    return 0.0;
}

struct OrderItem
{
    char partCode;
    size_t quantity;

    OrderItem(char partCode, size_t quantity)
        : partCode(partCode), quantity(quantity)
    {
    }
};

struct Order
{
    int code;
    std::vector<OrderItem> items;

    Order(int code)
       : code(code)
    {
    }

    void addItem(char partCode, size_t quantity)
    {
        for (OrderItem &item : items)
        {
            if (item.partCode == partCode)
            {
                item.quantity += quantity;
                return;
            }
        }
        items.push_back(OrderItem(partCode, quantity));
    }

    double totalCost() const
    {
        double total = 0.0;
        for (const OrderItem &item : items)
        {
            total += (costOfPart(item.partCode) * item.quantity);
        }
        // TOOD: fees, taxes, discounts, etc...
        return total;
    }
};

std::vector<Order> orders;

double costOfAllOrders()
{
    double total = 0.0;
    for(const Order &order : orders)
    {
        total += order.totalCost();
    }
    return total;
}

double costOfOrder(int orderCode)
{
    for(const Order &order : orders)
    {
        if (order.code == orderCode)
            return order.totalCost();
    }
    return 0.0;
}

...

parts.push_back(Part('A', 10.0));
parts.push_back(Part('B', 20.0));

...

Order order(12345);
order.addItem('A', 1);
orders.push_back(order);

...

double costOfOneOrder = costOfOrder(12345);
double totalCostOfOrders = costOfAllOrders();
...

Или, если вы действительно хотите использовать std::accumulate(), тогда вы можете сделать что-то вроде этого:

#include <algorithm>
#include <numeric>

struct Part
{
    char code;
    double cost;

    Part(char code, double cost)
        : code(code), cost(cost)
    {
    }
};

std::vector<Part> parts;

double costOfPart(char code)
{
    auto iter = std::find_if(parts.begin(), parts.end(),
        [=](Part &part){ return part.code == code; }
    );
    if (iter != parts.end())
        return iter->cost;
    return 0.0;
}

struct OrderItem
{
    char partCode;
    size_t quantity;

    OrderItem(char partCode, size_t quantity)
        : partCode(partCode), quantity(quantity)
    {
    }
};

struct Order
{
    int code;
    std::vector<OrderItem> items;

    Order(int code)
       : code(code)
    {
    }

    void addItem(char partCode, size_t quantity)
    {
        auto iter = std::find_if(items.begin(), items.end(),
            [=](OrderItem &item){ return item.partCode == partCode; }
        );
        if (iter != items.end())
            iter->quantity += quantity;
        else
            items.emplace_back(partCode, quantity);
    }

    double totalCost() const
    {
        double total = std::accumulate(items.begin(), items.end(), 0.0,
            [](double totalSoFar, const OrderItem &item) {
                return totalSoFar + (costOfPart(item.partCode) * item.quantity);
            }
        );
        // TOOD: fees, taxes, discounts, etc...
        return total;
    }
};

std::vector<Order> orders;

double costOfAllOrders()
{
    return std::accumulate(orders.begin(), orders.end(), 0.0,
        [](double totalSoFar, const Order &order){
            return totalSoFar + order.totalCost();
        }
    );
}

double costOfOrder(int orderCode)
{
    auto iter = std::find_if(orders.begin(), orders.end(),
        [=](Order &order){ return order.code == orderCode; }
    );
    if (iter != orders.end())
        return iter->totalCost();
    return 0.0;
}

...

parts.emplace_back('A', 10.0);
parts.emplace_back('B', 20.0);

...

Order order(12345);
order.addItem('A', 1);
orders.push_back(order);

...

double costOfOneOrder = costOfOrder(12345);
double totalCostOfOrders = costOfAllOrders();
...

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

auto partCost = [&](char code) -> int {
    for(auto &p : partsVec) {
        if (p.code == code)
            return p.cost;
    }
    return 0;
}

int totalCost = 0;
for(auto &c : customers){
    totalCost += accumulate(c.partsList.begin(), c.partsList.end(), 0,
        [&](int totalSoFar, char code) {
            return totalSoFar + partCost(code);
        }
    );
}

Или просто используя простые циклы:

void test(){
    int cost = 0;
    for(unsigned i = 0; i < customers.size(); i++) {
        auto &c = customers[i];
        for(unsigned x = 0; x < c.partsList.size(); x++) {
            auto partCode = c.partsList[x];
            for(unsigned z = 0; z < partsVec.size(); z++) {
                auto &p = partsVec[z];
                if (p.code == partCode) {
                    cost += p.cost;
                    break;
                }
            }
        }
    }
    cout << cost << endl;
}
1 голос

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

std::accumulate(order.begin(), order.end(), 0, [&parts](const auto & o) {
    return std::find(parts.begin(), parts.end(), o).cost();
}

Вы также можете попробовать написать «неприятный» функциональный объект, который будет вести себя как лямбда.

class AccumulatorHelper {
public:
    vector<Parts>& parts;
    AccumulatorHelper(vector<Parts>& p): parts(p) { }
    int operator()(const Order& order) {
        return std::find(parts.begin(), parts.end(), order.character());
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...