Я хотел бы создать класс, который
- преобразующий произвольные заданные показатели для дополнительных индексов 0 на основе
- обертывания 1D массив таким образом, что вы можете получить доступ к нему в качестве 2D массив с использованием преобразованных индексов
рабочий пример будет выглядеть примерно так
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdexcept>
#include <iterator>
#include <cassert>
using namespace std;
class DataFrame
{
vector<int> data;
public:
typedef vector<ssize_t> idx_t;
private:
idx_t rowIdx;
idx_t colIdx;
public:
DataFrame(const idx_t &rowIdx, const idx_t &colIdx)
: data(rowIdx.size() * colIdx.size())
, rowIdx(rowIdx)
, colIdx(colIdx)
{
assert(is_sorted(rowIdx.begin(), rowIdx.end()));
assert(is_sorted(colIdx.begin(), colIdx.end()));
}
int& operator()(int i, int j)
{
idx_t::iterator itI, itJ;
itI = lower_bound(rowIdx.begin(), rowIdx.end(), i);
if(rowIdx.end() == itI || i != *itI) throw out_of_range("could not find specified row");
itJ = lower_bound(colIdx.begin(), colIdx.end(), j);
if(colIdx.end() == itJ || j != *itJ) throw out_of_range("could not find specified col");
return data[distance(rowIdx.begin(), itI)*colIdx.size() +
distance(colIdx.begin(), itJ)];
}
vector<int> & getData() { return data; }
};
int main()
{
DataFrame::idx_t rI, cI;
rI.push_back(3);
rI.push_back(5);
cI.push_back(2);
cI.push_back(3);
cI.push_back(10);
DataFrame df(rI, cI);
df(3,2) = 1;
df(3,3) = 2;
df(3,10) = 3;
df(5,2) = 4;
df(5,3) = 5;
df(5,10) = 6;
ostream_iterator<int> out_it(cout, ", ");
copy(df.getData().begin(), df.getData().end(), out_it);
cout << endl;
return 0;
}
Произвольные индексы каждой строки/столбца указаны в векторе. Для поддержания некоторой производительности код требует, чтобы индексы монотонно увеличивались.(Если у вас есть C++ 11, это проверяется в ctor, если у вас нет C++ 11, то у вас нет функции is_sorted
. Кроме того, этот код не проверяет уникальность произвольных индексов.)
Когда вы получаете доступ к данным, он просто выполняет двоичный поиск по каждому вектору индексов, чтобы найти позицию в векторе, которая соответствует произвольному индексу, и использует эту позицию в качестве соответствующего индекса для базовых данных. Существует простое преобразование из двумерных индексов в 1D-индекс.
Возможно, вы захотите проверить, что моя проверка ошибок индекса верна для всех комбинаций плохих/хороших показателей, если вам нужно об этом беспокоиться.
Я оставлю его вам, чтобы добавить дополнительную надежность/функциональность с точки зрения const
аксессуаров, различных конструкторов и т. Д. Если вы хотите обобщить это на массивы измерения, отличные от 2, я рекомендую вам создать класс для просто конвертируя произвольный индекс в индекс, основанный на 0, и который избавится от некоторых повторений кода, которые у меня есть. Существуют также другие способы сделать преобразование произвольного индекса в индекс на основе 0, например, с map
, как и другие. В этом случае, однако, есть некоторые проблемы, такие как создатель map
должен был бы гарантировать, что если говорят 10 столбцов, каждый индекс в [0, 10] появляется ровно один раз как значение на карте.
, так что бывшее 'Martix [0] [0] = 1' будет доступно посредством произвольного индекса, например,' Matrix [0] [5] '? – perreal
Вам нужно будет определить собственный класс матрицы. Массивы в C++ являются примитивами для смежных блоков памяти, индексированных смежными целыми числами. – StoryTeller
Схема индексации, которую вы имеете в виду здесь, совершенно неясна. –