C++ 从QList中删除重复对象
我有一个C++ 从QList中删除重复对象,c++,qt,list,qlist,C++,Qt,List,Qlist,我有一个QList,其中MyData有两个成员,int-id(唯一)和QString-name。我想删除基于名称的所有重复条目,并且该条目必须是具有相同名称的其他对象之间的最高id。有没有关于如何以最快的方式做这件事的建议?在这里,性能是一个非常重要的因素 我在谷歌搜索了一整天后的一些想法: qStableSort()它基于id(降序),然后循环通过QList,然后对于每个条目,当新的QList上不存在名称时,将条目复制到另一个新的QList 使用QList::toSet(删除所有重复条目),
QList
,其中MyData
有两个成员,int-id
(唯一)和QString-name
。我想删除基于名称
的所有重复条目,并且该条目必须是具有相同名称
的其他对象之间的最高id
。有没有关于如何以最快的方式做这件事的建议?在这里,性能是一个非常重要的因素
我在谷歌搜索了一整天后的一些想法:
它基于id(降序),然后循环通过qStableSort()
,然后对于每个条目,当新的QList
上不存在QList
名称时,将条目复制到另一个新的
QList
- 使用
(删除所有重复条目),并基于QList::toSet
提供运算符==()和qHash()实现,但唯一条目可能没有最高idname
- 使用
,但我不确定它是如何工作的std::list::unique
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 );
}
这个怎么样:
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.
QList theList=。。。;
QHash nameToIdMap;
for(常量MyData&元素:列表){
auto iter=nameToIdMap.find(element.name);
if(iter!=nameToIdMap.end()&&iter.second>element.id){
//如果映射中存在项(名称已出现),且ID为
//大于当前元素,只需跳过当前元素。
继续;
}
//否则,请在地图中插入/覆盖它。
nameToIdMap[element.name]=element.id;
});
//nameToIdMap现在应该将唯一名称映射到最高ID。如果需要,
//您可以通过迭代映射的条目将其复制回新列表
//并相应地创建新的MyData元素。
在我看来,这样做的好处是:您不必将列表转换为std
-容器并返回,如果您找到一种方法继续使用QMap
而不是QList
,您只需在初始列表上迭代一次。而QHash
将为您提供摊销O(1)
查找复杂性
编辑:更改为
QHash
我是通过STL容器完成的,但我认为将其转换为Qt容器并不困难
包括
#包括
#包括
#包括
使用标准的C++库函数(5个< /P>:要么<代码> STD::清单:独特的或“一般<代码> STD::独特的< /代码>函数”)意味着你必须将数据复制到一个标准容器,然后将它们复制回QList。你已经使用lambdas——为什么不进行排序和设置比较?@致命吉他,我不喜欢长的lambdas,这就是为什么我没有在sort中使用它。另一方面,我不知道如何在集合定义中使用lambda。在我的示例中,你能告诉我如何通过lambda声明集合吗?谢谢,显然在集合定义中是不可能的。。太糟糕了,我什么都喜欢使用lambdas。这也是一个好主意,但我在问题中漏掉了一个要点:我在MyData
中实际上有两个以上的成员。我的缺点:(这不是什么大问题:只需使用QHash
,然后将if
-语句的第二个条件更改为:iter.second.id>element.id
。或者将MyData*
放入QHash,以避免复制所有MyData.+1:语法很酷!我必须尽快切换到新标准:-)
// 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());
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.
#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;
} );
}