如何处理矢量以获得所需的输出?

时间:2012-10-02 18:48:08

标签: c++ vector

我自己学习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中的其他所需处理,我使用 foreach if 语句。 我正在尝试不同的C ++方法,但没有任何作用。我完全失去了...... 另外我知道Boost Library中有一些功能,但暂时我不想去那里,更喜欢先学习基础知识。

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

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

2 个答案:

答案 0 :(得分:3)

第一步,即在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> >而不是三个单独的向量中。

答案 1 :(得分: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而不是迭代器。