STL 中是否有像 std::unique 这样的算法来存储相等对象的数量?

Is there an algorithm in STL like std::unique which stores the amount of equal objects?

提问人:Damir Tenishev 提问时间:11/12/2023 最后编辑:Damir Tenishev 更新时间:11/12/2023 访问量:104

问:

std::unique 算法在连续的元素组中仅保留唯一元素。同时,有时了解初始容器中有多少特定元素是很有用的。喜欢用元素的数量及其数量进行卷积。

STL 中是否有这样的算法或一些简单的方法来做到这一点,而不考虑从头开始编写整个代码(这很容易,但我想尽可能多地重用现有解决方案)并避免额外的容器,例如 等?关键是要有一个简单明了的解决方案,比如 .std::unordered_mapstd::equal

似乎使用额外的迭代器来写入金额或使用将存储值及其金额的位置。std::uniquestd::uniquestd::pairfirstsecond

例如

对于容器

[1, 1, 2, 2, 1, 1]

因此,我希望有两个容器 [1,2,1] 和 [2,2,2],其中第一个保留值,第二个容器将它们的数量保存在连续的组中(在这种情况下,[1,2] 和 [4,2] 可能是一个选项,但这是一个略有不同的主题)一个容器,如 [{1,2}, {2,2}, {1,2}]。

C++ 标准

评论

0赞 Some programmer dude 11/12/2023
自然的蛮力方式大概是针对容器中的每个元素,计算出现的次数。
0赞 Igor Tandetnik 11/12/2023
你到底想生产什么?连续元素的组数?比如说,对于序列,正确的结果应该是什么 - 2、3、别的什么?目前尚不清楚您希望获得什么最终结果。[1, 1, 2, 2, 1, 1]
0赞 Nicol Bolas 11/12/2023
这不是一个算法;它将是一个查找唯一聚类的视图,其元素是一系列此类聚类。
0赞 Damir Tenishev 11/12/2023
@Someprogrammerdude当然,正如我在问题中所说,这是可以做到的。除了 std::equal 之外,还可以在没有 STL 的情况下“以自然蛮力的方式”完成。我的问题只是想知道我是否错过了一些准备好避免重新发明自行车的东西。“准备好”是指一种算法或它们的某种组合,如 Nicol,可能在下面建议。
1赞 Some programmer dude 11/13/2023
有时根本没有简单的现有解决方案,而幼稚或蛮力和“一年级作业”解决方案也许是最好的?你接受的范围答案,它真的在所有可能方面都更好吗?它是否更容易阅读和理解?即使匆匆一瞥?调试更容易吗?更容易维护?不要把事情搞得太复杂,它只会让下一个程序员更难处理你的代码(当你忘记了这一切时,可能在一两年内就是你自己)。不要仅仅因为解决方案看起来太简单而忽视它们。

答:

4赞 康桓瑋 11/12/2023 #1

在 的帮助下,您可能希望使用 views::chunk_by<ranges>

auto l = {1, 1, 2, 2, 1, 1};
auto r = l | std::views::chunk_by(std::ranges::equal_to{})
           | std::views::transform([](auto chunk) {
               return std::pair{chunk.front(), chunk.size()};
             });

演示

如果需要分别收集数字和金额,可以使用 views::keys/views:values

auto numbers = r | std::views::keys;
auto amounts = r | std::views::values;

演示

评论

0赞 Damir Tenishev 11/12/2023
谢谢。这个很符合我的需求。两个问题。(1) 使用这种实现,在大量数据(千兆字节)上的性能不会比简单的暴力循环差吗?我的意思是,这个管道会根据性能生成代码吗?从提供的演示及其代码中很难一目了然。从性能角度来看,是否有任何可能的水下石头,例如过多的副本、中间分配等?(2) 有没有办法实现类似的结果,它将返回两个单独的容器 - 带有数字和金额?
1赞 康桓瑋 11/12/2023
@DamirTenishev我不认为这里有可观察到的性能影响,视图不存储数据,因此不涉及分配。没有必要使用涉及动态分配的容器,只需使用即可获取不同的视图。views::keys/views::values
0赞 Toby Speight 11/13/2023
@Danir,这里介绍的 THE 在 _input_range 时可以正常工作,但分离并需要_forward_range,因此最好调整您的代码以接受对而不是单独的范围。rlnumbersamounts