我有一个(i,j,k)格式的巨大表格(大约50Gb)(来自稀疏矩阵)存储为</ p>
uint32_t * idx1, * idx2;
float * vals;
uint32_t tablesize;
我希望使用给定的比较函数对其进行排序,该函数是idx1和idx2的函数。可以使用std :: sort来完成吗?
具体地,通过将id放在idx1中的id,在idx2中的j,以及在val中的相应条目中的v,存储在稀疏矩阵中具有值v的每个非零条目(i,j)。我想根据(i1,j1,v1)&lt; =(i2,j2,v2)对这些条目进行排序,如果
(i1 < i2) || (i1==i2 && j1 <= j2)
我能够在非标准数据类型上使用std :: sort的例子假设被比较的每个项目是一个类的单个实例;这里每个项目由不同数组中的三个值表示。
答案 0 :(得分:3)
遗憾的是,很难说服std::sort
或任何标准库使用条带化数据。它旨在假设数据可以通过单个=
复制,通过一个move
移动或通过一个swap
进行交换。
最好的办法是使用boost::iterator_facade
编写一个包装数据的自定义迭代器类,并隐藏std::sort
的条带化数据格式。我过去想做类似的事情,但我的工作区不允许我们使用boost
。 编辑:当您的外观被取消引用时,可能需要创建某种可以分配/移动/交换的代理对象,并对每个条带数组执行正确的操作。这不是一件轻而易举的事。
下一个最好的选择是从0到N创建一个int
的数组,每个数组代表条带数据数组的索引。写一个自定义仿函数给std::sort
,它对这个数组进行排序以符合你的标准。当你有这么大的数据集时,它显然远非理想。
答案 1 :(得分:1)
如果您必须继续使用现有的数据结构(基本上是std::tuple
三个std::vector
,那么使用boost::zip_iterator
似乎将是要走的路。 zip_iterator
将三个迭代器(两个索引和一个值)视为单个元组,您可以使用自定义比较函数对象对数据进行就地排序。唉,boost::zip_iterator
无法与std::sort
一起使用,如this Q&A中所述,因为它无法写入。
这意味着您必须编写自己的zip_iterator类,可以与std::sort
一起使用。请注意,这不是一项简单的练习,请参阅this Q&A和/或此paper。
对std::vector
的{{1}}进行排序要容易得多。我在下面的尝试使用std::tuple
两个索引和一个值,并将这些条目存储到std::tuple
中。对于排序,我使用C ++ 14泛型lambda,将两个索引转发为一个较小的元组,并使用std::vector
的{{1}}字符串按字典顺序(即首先在行索引上,然后在列索引上)进行比较。 {1}}。
operator<
如果您的应用程序可以使用此转换后的数据布局(并且可能存在缓存性能原因,那么上面的代码将根据您的需要进行排序。
注意:正如@Casey所提到的,您也可以使用std::tuple
代替#include <algorithm>
#include <iostream>
#include <tuple>
#include <vector>
using index = uint32_t;
using value = float;
using sparse_entry = std::tuple<index, index, value>;
using sparse_matrix = std::vector<sparse_entry>;
int main()
{
// sparse 3x3 matrix
auto m = sparse_matrix {
std::make_tuple( 1, 1, -2.2),
std::make_tuple( 1, 0, 42 ),
std::make_tuple( 0, 2, 3.4),
std::make_tuple( 0, 1, 1.7)
};
// sort by row-index, then column-index
std::sort(begin(m), end(m), [](auto const& L, auto const& R) {
return
std::forward_as_tuple(std::get<0>(L), std::get<1>(L)) <
std::forward_as_tuple(std::get<0>(R), std::get<1>(R))
;
});
for (auto const& elem : m)
std::cout << "{ " << std::get<0>(elem) << ", " << std::get<1>(elem) << ", " << std::get<2>(elem) << "}, \n";
}
,但是当您将std::tie
更改为完整内容时,这可能会让您感到困惑成熟的用户定义类,其中getters按值返回。