如何解决迭代除当前对象之外的所有其他对象
在许多应用程序中需要计算对象序列之间的相互交互,即对于序列中的每个对象,迭代除/跳过/排除当前对象之外的所有其他对象。 这是我目前的解决方案:
std::vector<Object> objects;
for( auto icurr=objects.begin(); icurr!=objects.end(); ++icurr )
{// Iterate over all the other objects excluding this one
for( auto iother=objects.begin(); iother!=icurr; ++iother )
icurr->interact_with(*iother);
for( auto iother=icurr+1; iother!=objects.end(); ++iother )
icurr->interact_with(*iother);
}
但这并不能让我满意,因为它很麻烦,而且最重要的是重复了循环体。 我也不喜欢平庸的选择:
for( auto icurr=objects.begin(); icurr!=objects.end(); ++icurr )
{
for( auto iother=objects.begin(); iother!=objects.end(); ++iother )
if(icurr!=iother) icurr->interact_with(*iother);
}
因为有一个可以避免的测试;在这种情况下,我宁愿写这样的东西:
for( Object& curr : objects )
{
for( const Object& other : objects.excluded(curr) )
curr.interact_with(other);
}
如果它具有相同的性能,那将是一个主要的可读性增益。我可以利用最新的 C++ 标准来提高代码的可读性吗?有什么建议吗? 免责声明:这是一个编码风格问题,试图保持最新的最佳实践、学习和改进。
解决方法
我不认为我会编写一个整体单独的 excludes 函数,因为这样你最终会重新分配整个对象向量减去一个元素。不要过度设计基于 for 循环的索引可以做什么。
for (size_t i = 0; i < objects.size(); i++) {
for (size_t j = 0; j < objects.size(); j++) {
if (i == j) continue;
objects[i].interact_with(objects[j]);
}
}
,
使用范围库,您可以执行以下操作:
for (const Object& curr : objects) {
for (const Object& other : objects | ranges::filter([&](const Object& obj) { return &obj != curr; }) )
curr.interact_with(other);
}
但这确实会做额外的比较。
您的第一个版本似乎是最佳的。
使用 std::span
(C++20)(或重新实现的版本),您可能会这样做,以避免重复,例如:
std::vector<Object> objects;
for (auto it = objects.begin(); it != objects.end(); ++it) {
for (auto range : {std::span{objects.begin(),it},std::span{it + 1,objects.end()}}) {
for (const auto& other : range) {
it->interact_with(other);
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。