微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

迭代除当前对象之外的所有其他对象

如何解决迭代除当前对象之外的所有其他对象

在许多应用程序中需要计算对象序列之间的相互交互,即对于序列中的每个对象,迭代除/跳过/排除当前对象之外的所有其他对象。 这是我目前的解决方案:

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 举报,一经查实,本站将立刻删除。