我有一个QList<MyData>,其中MyData有两个成员,int id (唯一)和QString name。我想删除基于name的所有重复条目,并且该条目必须是具有相同name的其他对象之间的最高id。对如何以最快的方式做这件事有什么建议吗?在这里,性能是一个非常重要的因素。
在Google编辑了一整天之后,我的一些想法:
qStableSort()基于id (降序),然后循环遍历QList,然后在新的QList上不存在name时,将条目复制到另一个新的QList中。QList::toSet (删除所有重复条目),并提供基于name的operator==()和qHash()实现,但是唯一条目可能没有最高的idstd::list::unique,但我不确定它是如何工作的。发布于 2013-01-14 13:56:48
std::list::unique可以使用具有以下属性的函数作为参数:
二进制谓词,它使用两个类型与列表中包含的值相同的值,返回true以删除作为第一个参数从容器中传递的元素,否则返回false。这将是一个函数指针或函数对象。
因此,在您的情况下,您可以使用折叠函数:
bool shouldRemove(MyData first, MyData second)
{
// remove only if they have the same name and the first id
// is smaller than the second one
return ( first.name == second.name &&
first.id <= second.id );
}简单地说就是这样,
std::list<MyData> myList = qlist.toStdList();
myList.unique(shouldRemove)注意,您需要首先对std::list进行排序。
编辑
您似乎可以将std::unique与Qt containers结合使用(如果Qt是用STL支持构建的)。因此,在这种情况下,您可以执行以下操作:
// lessThan is a function that sorts first by name and then by id
qSort(qList.begin(), qList.end(), lessThan );
QList<MyData>::iterator it = std::unique (qList.begin(), qList.end(), shouldRemove);
qList.erase(it, qList.end());发布于 2013-01-14 14:29:16
这个怎么样:
QList<MyData> theList = ...;
QHash<QString, int> nameToIdMap;
for (const MyData& element : theList) {
auto iter = nameToIdMap.find(element.name);
if (iter != nameToIdMap.end() && iter.second > element.id) {
// If item exists in map (name already occured) and the ID is
// bigger than in the current element, just skip the current element.
continue;
}
// Otherwise, insert/overwrite it in the map.
nameToIdMap[element.name] = element.id;
});
// nameToIdMap should now map unique names to highest IDs. If desired,
// you could copy it back into a new list by iterating over the map's entries
// and creating new MyData elements accordingly.在我看来,这样做的好处是:您不必将列表转换为std-container并返回,如果您找到了一种继续使用QMap而不是QList的方法,那么您只需要在初始列表上迭代一次。QHash会给你摊销的O(1)查找复杂性。
编辑:更改为QHash。
发布于 2013-01-14 14:33:16
我是用STL容器做的,但我认为把它转换成Qt容器并不难。
包括
#include <list>
#include <set>
#include <iostream>
#include <algorithm>
struct MyData {
int id;
std::string name;
};
struct MyDataSortComparator {
bool operator()( const MyData & left, const MyData & right ) {
if ( left.name < right.name ) {
return true;
}
else if ( left.name > right.name ) {
return false;
}
return left.id > right.id;
}
};
struct MyDataSetComparator {
bool operator()( const MyData & left, const MyData & right ) {
return left.name < right.name;
}
};
int main() {
std::list< MyData > theList = {
{ 1, "Dickson" },
{ 2, "Dickson" },
{ 3, "Dickson" },
{ 2, "borisbn" },
{ 1, "borisbn" }
};
std::set< MyData, MyDataSetComparator > theSet;
theList.sort( MyDataSortComparator() );
std::for_each( theList.begin(), theList.end(), []( const MyData & data ) {
std::cout << data.id << ", " << data.name << std::endl;
} );
std::for_each( theList.begin(), theList.end(), [&theSet]( const MyData & data ) {
theSet.insert( data );
} );
std::cout << "-------------------" << std::endl;
std::for_each( theSet.begin(), theSet.end(), []( const MyData & data ) {
std::cout << data.id << ", " << data.name << std::endl;
} );
}http://liveworkspace.org/code/wOFnM$5
https://stackoverflow.com/questions/14319474
复制相似问题