2015-07-16 5 views
10

मेरी वर्तमान परियोजना में मैं एक बहुआयामी डेटास्ट्रक्चर से निपट रहा हूं। अंतर्निहित फ़ाइल अनुक्रमिक रूप से संग्रहीत है (यानी एक विशाल सरणी, वेक्टर का कोई वेक्टर नहीं)। इन डेटास्ट्रक्चर का उपयोग करने वाले एल्गोरिदम व्यक्तिगत आयामों के आकार को जानने की आवश्यकता है।जेनेरिक सी ++ बहुआयामी इटरेटर

मुझे आश्चर्य है कि एक बहुआयामी इटरेटर वर्ग को सामान्य तरीके से कहीं और निश्चित किया गया है और यदि इससे निपटने के तरीके पर कोई मानक या पसंदीदा तरीके हैं।

फिलहाल मैं कुछ अतिरिक्त विधियों के साथ एक रैखिक इटरेटर का उपयोग कर रहा हूं जो प्रत्येक आयाम के आकार को वापस कर देता है और पहले भाग में कितने आयाम हैं। कारण मुझे यह पसंद नहीं है क्योंकि मैं उदाहरण के लिए एक उचित तरीके से std :: दूरी का उपयोग नहीं कर सकता (यानी केवल पूरी संरचना की दूरी लौटाता है, लेकिन अलग-अलग आयाम के लिए नहीं)।

अधिकांश भाग के लिए मैं एक रैखिक फैशन में डेटास्ट्रक्चर का उपयोग करूंगा (पहला आयाम खत्म करने के लिए शुरू होता है -> अगला आयाम + ... और इसी तरह), लेकिन यह जानना अच्छा होगा कि एक आयाम "समाप्त होता है"। मुझे नहीं पता कि इस तरह के दृष्टिकोण में ऑपरेटर *(), ऑपरेटर +() और ऑपरेटर ==() के साथ ऐसा कैसे करें।

वैक्टर दृष्टिकोण का एक वेक्टर डिफॉल्ट किया गया है, क्योंकि मैं फ़ाइल को विभाजित नहीं करना चाहता हूं। इसके अलावा एल्गोरिदम को विभिन्न आयामों के साथ संरचना पर काम करना चाहिए और इसलिए सामान्य बनाना मुश्किल है (या शायद कोई रास्ता है?)।

बूस्ट मल्टी_एरे में समान समस्याएं हैं (इटरेटर के एकाधिक "स्तर")।

मुझे आशा है कि यह बहुत अस्पष्ट या अमूर्त नहीं है। सही दिशा में किसी भी संकेत की सराहना की जाएगी।

मैं अपने आप को फिर से समाधान ढूंढ रहा था और बूस्ट :: mult_array का पुनरीक्षण कर रहा था। चूंकि यह पता चला है कि उनके साथ डेटा पर उप दृश्य उत्पन्न करना संभव है, लेकिन साथ ही साथ शीर्ष स्तर पर प्रत्यक्ष इटरेटर भी लेना चाहिए और डेटा संरचना को "फ़्लैट" करना चाहिए। मल्टी_एरे के लागू संस्करण हालांकि मेरी आवश्यकताओं के अनुरूप नहीं हैं, इसलिए मैं शायद एक स्वयं को लागू करूंगा (जो पृष्ठभूमि में फ़ाइलों की कैशिंग को संभालता है) जो अन्य बहु_आरे के साथ संगत है।

कार्यान्वयन के बाद मैं इसे फिर से अपडेट कर दूंगा।

+1

ऐसा लगता है कि आपको बहुआयामी इटरेटर स्वयं को लागू करना है। बस ऑपरेटरों को अपने आप को सीमित न करें: आप प्रत्येक आयाम में वर्तमान स्थिति के बारे में जानकारी पूछने के लिए नामित विधियों का उपयोग कर सकते हैं। –

+2

यह सवाल दिलचस्प है। ऐसी सूचनाएं प्रदान करने के लिए मुझे मिला एकमात्र तरीका यह है कि बहु-सूचकांक को कम कर सकें। फ्लैटन इंडेक्स (और इसके विपरीत) से '{x, y, z}'। मैं नहीं देखता कि आप उस उद्देश्य के लिए अपनी खुद की कस्टम कक्षा प्रदान किए बिना "मानक" तरीके से कैसे कर सकते हैं। – coincoin

+0

त्वरित उत्तर के लिए दोनों धन्यवाद। @ सर्जरोगैच: मैंने जो भी सोचा था, वह ऐसा लगता है, लेकिन ऐसा लगता है कि "विरोधी-मूर्खतापूर्ण"। – Lazarus535

उत्तर

2

मैंने अभी गिटूब पर एक सार्वजनिक भंडार खोलने का निर्णय लिया है: MultiDim Grid जो आपकी आवश्यकताओं के लिए मदद कर सकता है। यह एक चल रही प्रोजेक्ट है इसलिए यदि आप इसे आजमा सकते हैं और मुझे बताएं कि आपको क्या याद आती है तो मुझे खुशी होगी।

मैंने कोडरव्यू पर इस topic के साथ इस पर काम करना शुरू कर दिया है।

यह बस रखो:

MultiDim ग्रिड एक फ्लैट uni आयामी सरणी जो बहु आयाम निर्देशांकों के बीच एक सामान्य तेजी से पहुँच प्रदान करते हैं और सूचकांक समतल का प्रस्ताव।

आपको एक कंटेनर व्यवहार मिलता है ताकि आपके पास इटरेटर तक पहुंच हो।

+0

धन्यवाद (आप दोनों) उत्तर और सूखी के लिए केवल बहुत देर से प्रतिक्रिया करने के लिए ... व्यस्त। अब तक मैंने अपना खुद का कार्यान्वयन किया है, जो आपके प्रोजेक्ट के समान नहीं है और मैं अब तक इससे खुश हूं। मैंने उस कोड को लंबे, लंबे समय तक छुआ नहीं है, क्योंकि यह वही करता है जो मैं चाहता था, लेकिन यदि मैं दोबारा करता हूं, तो मैं आपका कोड देखता हूं और शायद सेनाओं को जोड़ सकता हूं। – Lazarus535

1

यह लागू करना मुश्किल नहीं है। बस यह बताएं कि आपकी परियोजना की क्या कार्यक्षमता आवश्यक है। यहाँ एक गूंगा नमूना है।

#include <iostream> 
#include <array> 
#include <vector> 
#include <cassert> 

template<typename T, int dim> 
class DimVector : public std::vector<T> { 
public: 
    DimVector() { 
     clear(); 
    } 

    void clear() { 
     for (auto& i : _sizes) 
      i = 0; 
     std::vector<T>::clear(); 
    } 

    template<class ... Types> 
    void resize(Types ... args) { 
     std::array<int, dim> new_sizes = { args ... }; 
     resize(new_sizes); 
    } 

    void resize(std::array<int, dim> new_sizes) { 
     clear(); 
     for (int i = 0; i < dim; ++i) 
      if (new_sizes[i] == 0) 
       return; 
     _sizes = new_sizes; 
     int realsize = _sizes[0]; 
     for (int i = 1; i < dim; ++i) 
      realsize *= _sizes[i]; 
     std::vector<T>::resize(static_cast<size_t>(realsize)); 
    } 

    decltype(auto) operator()(std::array<int, dim> pos) { 
     // check indexes and compute original index 
     size_t index; 
     for (int i = 0; i < dim; ++i) { 
      assert(0 <= pos[i] && pos[i] < _sizes[i]); 
      index = (i == 0) ? pos[i] : (index * _sizes[i] + pos[i]); 
     } 
     return std::vector<T>::at(index); 
    } 

    template<class ... Types> 
    decltype(auto) at(Types ... args) { 
     std::array<int, dim> pos = { args ... }; 
     return (*this)(pos); 
    } 

    int size(int d) const { 
     return _sizes[d]; 
    } 


    class Iterator { 
    public: 
     T& operator*() const; 
     T* operator->() const; 
     bool operator!=(const Iterator& other) const { 
      if (&_vec != &other._vec) 
       return true; 
      for (int i = 0; i < dim; ++i) 
       if (_pos[i] != other._pos[i]) 
        return true; 
      return false; 
     } 
     int get_dim(int d) const { 
      assert(0 <= d && d < dim); 
      return _pos[d]; 
     } 
     void add_dim(int d, int value = 1) { 
      assert(0 <= d && d < dim); 
      _pos[d] += value; 
      assert(0 <= _pos[i] && _pos[i] < _vec._sizes[i]); 
     } 
    private: 
     DimVector &_vec; 
     std::array<int, dim> _pos; 
     Iterator(DimVector& vec, std::array<int, dim> pos) : _vec(vec), _pos(pos) { } 
    }; 

    Iterator getIterator(int pos[dim]) { 
     return Iterator(*this, pos); 
    } 

private: 
    std::array<int, dim> _sizes; 
}; 

template<typename T, int dim> 
inline T& DimVector<T, dim>::Iterator::operator*() const { 
    return _vec(_pos); 
} 

template<typename T, int dim> 
inline T* DimVector<T, dim>::Iterator::operator->() const { 
    return &_vec(_pos); 
} 

using namespace std; 

int main() { 

    DimVector<int, 4> v; 
    v.resize(1, 2, 3, 4); 
    v.at(0, 0, 0, 1) = 1; 
    v.at(0, 1, 0, 0) = 1; 

    for (int w = 0; w < v.size(0); ++w) { 
     for (int z = 0; z < v.size(1); ++z) { 
      for (int y = 0; y < v.size(2); ++y) { 
       for (int x = 0; x < v.size(3); ++x) { 
        cout << v.at(w, z, y, x) << ' '; 
       } 
       cout << endl; 
      } 
      cout << "----------------------------------" << endl; 
     } 
     cout << "==================================" << endl; 
    } 
    return 0; 
} 

TODO सूची:

  • अनुकूलन: T const& का उपयोग जब संभव
  • optimizate इटरेटर: precompute realindex और उसके बाद सिर्फ इतना है कि realindex
  • बदलने को लागू const accessors
  • लागू ConstIterator
  • लागू करेंऔर operator<< फ़ाइल से
संबंधित मुद्दे