1

我自学 C++,因此在某些领域我有一些空白页,例如。对容器的一些操作,不同操作的名称等。因此请帮我解决这个问题。(我也很感激向我发送好的资源,这些资源将帮助我选择正确的容器和方法来处理它们。真正的实现示例将有很大帮助,因为这样更容易为我获取它。)

这是我的第一个“真正的”程序。我是用 PHP 编写的,但现在在学习时重写为 C++(我可以说它更具挑战性)。

简而言之,读取文件并创建 3 个不同的向量,其中包含相应的元素(人名、物品名称和物品数量)。例如(我知道这不是分配值的方法,它只是为了说明内容):

vector<string> vectorOfNames = {"Adam", "Eva", "Adam", "Adam", "Bruce"};
vector<string> vectorOfItems = {"Apple", "Apple", "Orange", "Pear", "Melon"};
vector<int> vectorOfAmount = {1, 9, 2, 4, 1};

现在,我想(按人和项目)表示它并计算(按数量)这些向量,例如。打印类似的东西:

All persons:
Adam
Eva
Bruce

All items:
Apple - 10
Orange - 2
Pear - 4
Melon - 1

Adam have:
Apple - 1
Orange - 2
Pear - 4

Eva have:
Apple - 9

Bruce have:
Melon - 1

在 PHP 中,我使用 *array_keys(array_flip())* 来获取唯一的名称和项目。在 C++ 中,我发现了这样的东西:

vector< string >::iterator r , w ;

set< string > tmpset ;

for( r = vectorOfNames.begin() , w = vectorOfNames.begin() ; r != vectorOfNames.end() ; ++r )
{
    if( tmpset.insert( *r ).second )
    {
        *w++ = *r ;
    }
}

vectorOfNames.erase( w , vectorOfNames.end() );

它运作良好,但问题是它修改了原始vectorOfNames。在应用它之前我应该​​将此向量复制到新向量还是有另一种方法?

至于 PHP 中所需的其余处理,我使用了foreachif语句。我正在为 C++ 尝试不同的方法,但没有任何效果。我完全迷失了......我也知道Boost Library中有一些功能,但我暂时不想去那里,更喜欢先学习基础知识。

另一方面,也许我应该使用其他容器,如地图或其他东西,使这个处理更容易?

所以如果你仍然知道我的意思并且你没有睡着,请把我推向正确的方向;)

4

2 回答 2

3

第一步,即在 a 中获取所有唯一名称,std::vector<std::string>我可能会这样做:

std::vector<std::string> tmp(original);
std::sort(tmp.begin(), tmp.end());
std::unique_copy(tmp.begin(), tmp.end(),
                 std::ostream_iterator<std::string>(std::cout, "\n"));

另一种解决方案可以使用辅助std::set<std::string>但不会按排序顺序打印名称:

std::set<std::string> mark;
std::copy_if(original.begin(), original.end(),
             [&](std::string const& value) { return mark.insert(value); });

(利用 C++ 2011 的特性)

其他操作不容易直接映射到 C++ 算法的工作方式。为了处理这些问题,我可能会使用不同的数据布局,例如,将数据存储在一个std::vector<std::tuple<std::string, std::string, int> >而不是三个单独的向量中。

于 2012-10-02T19:03:02.043 回答
0

这与您原来的方法很接近:

vector< string > vs;
vs.resize(vectorOfNames.size()); // more efficient if we already know the size

set< string > tmpset ;

vector< string >::const_iterator r;
for( r = vectorOfNames.begin() ; r != vectorOfNames.end() ; ++r )
{
    if( tmpset.insert( *r ).second )
    {
        vs.push_back(*r);
    }
}

但是,它使用辅助向量来存储新名称,因此您无需修改​​原始向量。为了保证您不会实际修改向量,此方法使用 const_iterator 而不是迭代器。

于 2012-10-02T19:42:45.800 回答