2011-08-11 11 views
0

私は私は何をしようとしたことは、次のMATLABコードを実装することで、簡単なMathWorks社のMATLABのような配列(実際には、今一次元のみ)を実装しようとしています:インデックスを使用したサブアレイ:どのように?

a=1:10; 
ind=find(a>5); 
a[ind]=5; 

私はSTDを行うためのvalarrayを持っていることを知っていますこれはスライスアレイを介して行われます。私はそれについて多くの詳細を知らない。コードは次のとおりです。

#include <iostream> 
using namespace std; 
template <typename T> class array 
{ 
public: 
    int m,n; //two dimensional at most 
    T *pdata; 
    //construct the array 
    array(){m=n=0;pdata=NULL;} //default is empty matrix 
    array(T a){m=n=1;pdata=new T[1];*pdata=a;} //array for scalar: array a=10; 
    array(int m0,int n0=1) {m=m0;n=1;pdata=new T[m];} 
    array(const array& a,int len=-1); 
    //destructor 
    ~array() {delete []pdata;} 
    //operator overloading 
    array<T>& operator+=(T s); 
    T& operator[](int i) {return pdata[i];} 
    array<T>& operator[](array<int> ind); 
    array<T>& operator=(const array<T>& a); 
    array<T>& operator=(T a) {for(int i=0;i<m;i++) pdata[i]=a;return *this;} 
    array<bool> operator>(T a); 
    array<bool> operator<(T a); 
    array<bool> operator==(T a); 
}; 

//copy a part of the other array 
template <typename T> array<T>::array<T>(const array<T>& a,int len) 
{ 
    if(len==-1) len=a.m*a.n; 
    if(len==0) {m=0;n=0;pdata=NULL;} 
    if(len>0) 
    { 
     m=len;n=1; 
     pdata=new T[len]; 
     for(int i=0;i<len;i++) pdata[i]=a.pdata[i]; 
    } 
} 

template <typename T> array<T>& array<T>::operator +=(T s) 
{ 
    for(int i=0;i<m*n;i++) pdata[i]+=s; 
    return *this; 
} 

//this function does not meet the purpose, it returns a reference to a temp obj 
template <typename T> array<T>& array<T>::operator[](array<int> ind) 
{ 
    array<T> ret(ind.m,ind.n); 
    for(int i=0;i<ind.m*ind.n;i++) 
    { 
     ret.pdata[i] = pdata[ind.pdata[i]]; 
    } 
    return ret; 
} 

template <typename T> array<bool> array<T>::operator>(T a) 
{ 
    array<bool> res(m*n); 
    for(int i=0;i<m*n;i++) res.pdata[i]=pdata[i]>a; 
    return res; 
} 

//helper function 
array<int> find(array<bool> a) 
{ 
    array<int> ret(a.m,a.n); //first use the same size space 
    int len=0; 
    for(int i=0;i<a.m*a.n;i++) 
    { 
     if(a.pdata[i]) {ret.pdata[len]=i;len++;} 
    } 
    return array<int>(ret,len); 
} 

/*ostream& operator<<(array<T>& a) 
{ 
    ostream os; 
    for(int i=0;i<a.m*a.n;i++) os>>a[i]>>'\t'; 
    return os; 
}*/ 

int main() 
{ 
    array<float> a(10); 
    for(int i=0;i<10;i++) a[i]=i; 
    for(i=0;i<10;i++) cout<<a[i]<<'\t'; 
    cout<<endl; 
    array<int> ind=find(a>5); 
    for(i=0;i<ind.m;i++) cout<<ind[i]<<'\t'; 
    cout<<endl; 
    a[ind]=5;//this will not work on the original array 
    //how do we support this????undefined 
    for(i=0;i<10;i++) cout<<a[i]<<'\t'; 
    cout<<endl; 

    return 0; 
} 

我々は一時アレイ上で作業しているので、最終aは全く変わっていません。 私は機能演算子を "知っている>が適切に実装されていませんが、私はこれを行う方法がわからない。誰もが私にヒントを与えることができます?ありがとう

答えて

0

アンドレア、ヒントありがとうございました。ほとんどあなたが言ったことは理にかなって、本当に助けになります。私は別のind_arrayを作成し、元の配列のアドレスを保持し、今は動作します! 唯一の変更は、演算子[]がind_arrayを返すことです。 ind_arrayの演算子= forが実際の代入を行うように定義されています。ここで

(そのシンプルな、私は今、二次元を削除するために)変更したコードされています

#include <iostream> 
using namespace std; 
template <typename T> class ind_array; 
template <typename T> class array 
{ 
public: 
    int len; //two dimensional at most 
    T *pdata; 
    //construct the array 
    array(){len=0;pdata=NULL;} //default is empty matrix 
    //array(T a){len=1;pdata=new T[1];*pdata=a;} //array for scalar: array a=10; 
    array(int m0) {len=m0;pdata=new T[len];} 
    array(const array& a,int len0=-1); 
    //destructor 
    ~array() {delete []pdata;} 
    int size() const {return len;} 
    //operator overloading 
    array<T>& operator+=(T s); 
    T& operator[](int i) {return pdata[i];} 
    ind_array<T> operator[](const array<int>& ind);//{return (ind_array(ind,pdata));} 
    array<T>& operator=(const array<T>& a); 
    array<T>& operator=(T a) {for(int i=0;i<len;i++) pdata[i]=a;return *this;} 
    array<bool> operator>(T a); 
    array<bool> operator<(T a); 
    array<bool> operator==(T a); 
}; 

//Index array or similar indirect-array as in valarray 
//this class shall keeps the array's address and the index 
template <typename T> class ind_array 
{ 
    array<int> ind; //an index array 
    T* ptr; //a pointer to the original data 
public: 
    int size() const {return ind.size();} 
    void operator=(T a){for(int i=0;i<size();i++) ptr[ind[i]]=a;} //assignment a value to a subarray 
    //how to construct the indx array then? 
    //according to valarry, the default constructor shall be prohibited 
    ind_array(const array<int>& indx,T* pt):ind(indx),ptr(pt){} //default constructor 
}; 

//copy a part of the other array 
template <typename T> array<T>::array<T>(const array<T>& a,int len0) 
{ 
    if(len0==-1) len0=a.len; 
    if(len0==0) {len=0;pdata=NULL;} 
    if(len0>0) 
    { 
     len=len0; 
     pdata=new T[len]; 
     for(int i=0;i<len;i++) pdata[i]=a.pdata[i]; 
    } 
} 

template <typename T> array<T>& array<T>::operator +=(T s) 
{ 
    for(int i=0;i<len;i++) pdata[i]+=s; 
    return *this; 
} 

//this function does not meet the purpose, it returns a reference to a temp obj 
//now we change it to return a indx_array which stores the original array's address 
template <typename T> ind_array<T> array<T>::operator[](const array<int>& ind) 
{ 
    /*array<T> ret(ind.len); 
    for(int i=0;i<ind.len;i++) 
    { 
     ret.pdata[i] = pdata[ind.pdata[i]]; 
    } 
    return ret;*/ 
    return (ind_array<T>(ind,pdata)); //call the constructor 
} 

template <typename T> array<bool> array<T>::operator>(T a) 
{ 
    array<bool> res(len); 
    for(int i=0;i<len;i++) res.pdata[i]=pdata[i]>a; 
    return res; 
} 

//helper function 
array<int> find(array<bool> a) 
{ 
    array<int> ret(a.len); //first use the same size space 
    int len=0; 
    for(int i=0;i<a.len;i++) 
    { 
     if(a.pdata[i]) {ret.pdata[len]=i;len++;} 
    } 
    return array<int>(ret,len); 
} 

/*ostream& operator<<(array<T>& a) 
{ 
    ostream os; 
    for(int i=0;i<a.m*a.n;i++) os>>a[i]>>'\t'; 
    return os; 
}*/ 

int main() 
{ 
    array<float> a(10); 
    for(int i=0;i<10;i++) a[i]=i; 
    for(i=0;i<10;i++) cout<<a[i]<<'\t'; 
    cout<<endl; 
    array<int> ind=find(a>5); 
    for(i=0;i<ind.len;i++) cout<<ind[i]<<'\t'; 
    cout<<endl; 
    a[ind]=5;//this will not work on the original array 
    //how do we support this????undefined 
    for(i=0;i<10;i++) cout<<a[i]<<'\t'; 
    cout<<endl; 

    return 0; 
} 
1

私はArraySliceクラスを作成し、operator []からそのインスタンスを返します。このクラスは、元Arrayへの参照を持っているでしょうし、前方がArrayへの呼び出しとして、ほとんどのメンバーを再実装する必要があります。例えば、ArraySlice::operator[]は、適切なインデックスとArray::operator[]を呼び出します。

+0

は、返信いただきありがとうございます。これは今私が理解するのが少し難しいです。ありがとう、私のためのコードの例を投稿することができます! – shangping

0

を私が考えるその共有アレイについて最良の解決策は元の(完全な)マトリックスと「ビュー」の両方に単一のタイプを持たせることです。 パラメータを設定するとe要素へのアクセスでは、両方とも同じ汎用コードを使用できます。また、元の完全な行列の実際のデータを含むクラスの中にオプションのstd :: vector要素を追加すると、メモリ処理が自動的になります。

これはこのアイデアの小さな実装です...選択のために私はstd::vectorの整数のペアを使用しました。 ArraySelectionに代入すると要素アクセス演算子が使用されるため、元の行列またはビューの両方で機能します。

メインプログラムは10x10マトリックスを割り当て、偶数/偶数、偶数/奇数、奇数/偶数、奇数/奇数の座標を持つ4つの異なる5x5ビューを作成します。 これらのビューは4つの異なる定数値に設定されています。 次に、フルマトリクスで選択が行われ、選択された要素に対して割り当てが行われます。最後に元のフルマトリックスが印刷されます。

#include <stdexcept> 
#include <vector> 
#include <functional> 
#include <algorithm> 

#include <stdio.h> 

typedef std::vector< std::pair<int, int> > Index; 

template<typename T> 
struct Array; 

template<typename T> 
struct ArraySelection 
{ 
    Array<T>& a; 
    Index i; 

    ArraySelection(Array<T>& a) 
     : a(a) 
    { 
    } 

    ArraySelection& operator=(const T& t) 
    { 
     for (int j=0,n=i.size(); j<n; j++) 
      a(i[j].first, i[j].second) = t; 
     return *this; 
    } 
}; 


template<typename T> 
struct Array 
{ 
    int rows, cols; 
    std::vector<T*> rptr; 
    int step; 

    std::vector<T> data; // non-empty if data is owned 

    T& operator()(int r, int c) 
    { 
     return rptr[r][c * step]; 
    } 

    Array(int rows, int cols, 
      Array *parent = NULL, 
      int row0=0, int rowstep=1, 
      int col0=0, int colstep=1) 
     : rows(rows), cols(cols), rptr(rows) 
    { 
     if (parent == NULL) 
     { 
      // Owning matrix 
      data.resize(rows*cols); 
      for (int i=0; i<rows; i++) 
       rptr[i] = &data[i*cols]; 
      step = 1; 
     } 
     else 
     { 
      // View of another matrix 
      for (int i=0; i<rows; i++) 
       rptr[i] = &((*parent)(row0 + i*rowstep, col0)); 
      step = colstep; 
     } 
    } 

    template<typename F> 
    ArraySelection<T> select(const F& f) 
    { 
     Index res; 
     for (int i=0; i<rows; i++) 
      for (int j=0; j<cols; j++) 
       if (f((*this)(i, j))) 
        res.push_back(std::make_pair(i, j)); 
     ArraySelection<T> ar(*this); 
     ar.i.swap(res); 
     return ar; 
    } 

    // Copy construction of a full matrix makes a full matrix, 
    // Copy construction of a view creates a view 
    Array(const Array& other) 
     : rows(other.rows), cols(other.cols), rptr(other.rptr), step(other.step) 
    { 
     if (other.data) 
     { 
      data = other.data; 
      for (int i=0; i<rows; i++) 
       rptr[i] = &data[i*cols]; 
     } 
    } 

    // Assignment is element-by-element optionally with conversion 
    template<typename U> 
    Array& operator=(const Array<U>& other) 
    { 
     if (other.rows != rows || other.cols != cols) 
      throw std::runtime_error("Matrix size mismatch"); 
     for(int i=0; i<rows; i++) 
      for (int j=0; j<cols; j++) 
       (*this)(i, j) = other(i, j); 
     return *this; 
    } 
}; 

int main() 
{ 
    Array<double> a(10, 10); 
    Array<double> a00(5, 5, &a, 0, 2, 0, 2); 
    Array<double> a01(5, 5, &a, 0, 2, 1, 2); 
    Array<double> a10(5, 5, &a, 1, 2, 0, 2); 
    Array<double> a11(5, 5, &a, 1, 2, 1, 2); 
    for (int i=0; i<5; i++) 
     for (int j=0; j<5; j++) 
     { 
      a00(i, j) = 1.1; 
      a01(i, j) = 2.2; 
      a10(i, j) = 3.3; 
      a11(i, j) = 4.4; 
     } 

    a.select(std::binder2nd< std::greater<double> >(std::greater<double>(), 3.5)) = 0; 

    for (int i=0; i<10; i++) 
    { 
     for (int j=0; j<10; j++) 
     { 
      printf(" %0.3f", a(i, j)); 
     } 
     printf("\n"); 
    } 
    return 0; 
} 
関連する問題