كيف يمكنني فرز الأمراض المنقولة جنسيا :: ناقلات من القيم من الأمراض المنقولة جنسيا مختلفا :: ناقلات الأمراض؟

StackOverflow https://stackoverflow.com/questions/236172

سؤال

ولدي عدة std::vector، كل من نفس الطول. أريد أن فرز واحد من هذه النواقل، وتطبيق التحول نفسه على كل من ناقلات أخرى. هل هناك طريقة أنيق للقيام بذلك؟ (يفضل استخدام STL أو زيادة)؟ بعض ناقلات عقد ints ومنهم من std::strings.

ورمز زائف:

std::vector<int> Index = { 3, 1, 2 };
std::vector<std::string> Values = { "Third", "First", "Second" };

Transformation = sort(Index);
Index is now { 1, 2, 3};

... magic happens as Transformation is applied to Values ...
Values are now { "First", "Second", "Third" };
هل كانت مفيدة؟

المحلول

ونهج friol هو جيد عندما تترافق مع يدكم. أولا، بناء ناقلات يتألف من الأرقام من 1 ... <م> ن ، جنبا إلى جنب مع عناصر من ناقلات يفرض شروطه على النظام فرز:

typedef vector<int>::const_iterator myiter;

vector<pair<size_t, myiter> > order(Index.size());

size_t n = 0;
for (myiter it = Index.begin(); it != Index.end(); ++it, ++n)
    order[n] = make_pair(n, it);

والآن يمكنك فرز هذه المجموعة باستخدام فارز مخصص:

struct ordering {
    bool operator ()(pair<size_t, myiter> const& a, pair<size_t, myiter> const& b) {
        return *(a.second) < *(b.second);
    }
};

sort(order.begin(), order.end(), ordering());

والآن كنت قد استولت على ترتيب إعادة ترتيب داخل order (على نحو أدق، في العنصر الأول من العناصر). يمكنك الآن استخدام هذا الطلب لفرز ناقلات الأخرى. ربما هناك ذكي جدا البديل في مكان قيد التشغيل في الوقت نفسه، ولكن حتى يأتي شخص آخر مع ذلك، وهنا واحدة البديل ليست في نفس المكان. ويستخدم order كجدول نظرة متابعة للمؤشر الجديد كل عنصر.

template <typename T>
vector<T> sort_from_ref(
    vector<T> const& in,
    vector<pair<size_t, myiter> > const& reference
) {
    vector<T> ret(in.size());

    size_t const size = in.size();
    for (size_t i = 0; i < size; ++i)
        ret[i] = in[reference[i].first];

    return ret;
}

نصائح أخرى

ووضع القيم الخاصة بك في زيادة الحاويات متعدد مؤشر ثم تكرار عبر لقراءة القيم في النظام الذي تريد. يمكنك حتى نسخها إلى ناقلات أخرى إذا كنت ترغب في ذلك.

typedef std::vector<int> int_vec_t;
typedef std::vector<std::string> str_vec_t;
typedef std::vector<size_t> index_vec_t;

class SequenceGen {
  public:
    SequenceGen (int start = 0) : current(start) { }
    int operator() () { return current++; }
  private:
    int current;
};

class Comp{
    int_vec_t& _v;
  public:
    Comp(int_vec_t& v) : _v(v) {}
    bool operator()(size_t i, size_t j){
         return _v[i] < _v[j];
   }
};

index_vec_t indices(3);
std::generate(indices.begin(), indices.end(), SequenceGen(0));
//indices are {0, 1, 2}

int_vec_t Index = { 3, 1, 2 };
str_vec_t Values = { "Third", "First", "Second" };

std::sort(indices.begin(), indices.end(), Comp(Index));
//now indices are {1,2,0}

والآن يمكنك استخدام ناقلات "مؤشرات" إلى مؤشر إلى ناقلات "القيم".

وحل تقريبي واحد فقط يتبادر إلى ذهني: إنشاء ناقلات وهذا هو مجموع كل ناقلات أخرى (ناقلات هياكل، مثل {3، الثالث، ...}، {1، أولا، ...}) ثم فرز هذه الموجه من قبل الحقل الأول، ومن ثم تقسيم الهياكل مرة أخرى.

ربما هناك حل أفضل داخل دفعة أو باستخدام المكتبة القياسية.

وربما يمكنك تحديد العرف "واجهة" مكرر أن يفعل ما تحتاجه هنا. فإنه تخزين المكررات لجميع ناقلات أو استخلاص بدلا من ذلك المكررات للجميع ولكن ناقلات الأول من إزاحة أولا. الجزء الصعب هو ما الذي dereferences مكرر إلى: التفكير في شيء من هذا القبيل دفعة :: الصفوف (tuple) وجعل استخدام ذكي للدفعة :: التعادل. (إذا كنت تريد توسيع على هذه الفكرة، يمكنك بناء هذه الأنواع مكرر بشكل متكرر باستخدام القوالب ولكن ربما كنت لا أريد أن أكتب نوع من ذلك - لذلك تحتاج إما ج ++ 0X السيارات أو وظيفة مجمع لالنوع الذي يأخذ نطاقات)

وأعتقد أن ما كنت <م> حقا الحاجة (ولكن تصحيح لي إذا كنت مخطئا) هو وسيلة للوصول إلى عناصر الحاويات في بعض الأمر.

وبدلا من إعادة ترتيب مجموعتي الأصلي، وأود أن استعارة مفهوم من تصميم قاعدة بيانات: إبقاء المؤشر، بناء على أمر من معيار معين. هذا المؤشر هو المراوغة الزائدة التي تقدم مرونة كبيرة.

وبهذه الطريقة فمن الممكن لتوليد مؤشرات متعددة وفقا لمختلف أعضاء فئة.

using namespace std;

template< typename Iterator, typename Comparator >
struct Index {
    vector<Iterator> v;

    Index( Iterator from, Iterator end, Comparator& c ){
        v.reserve( std::distance(from,end) );
        for( ; from != end; ++from ){
            v.push_back(from); // no deref!
        }
        sort( v.begin(), v.end(), c );
    }

};

template< typename Iterator, typename Comparator >
Index<Iterator,Comparator> index ( Iterator from, Iterator end, Comparator& c ){
    return Index<Iterator,Comparator>(from,end,c);
}

struct mytype {
    string name;
    double number;
};

template< typename Iter >
struct NameLess : public binary_function<Iter, Iter, bool> {
    bool operator()( const Iter& t1, const Iter& t2 ) const { return t1->name < t2->name; }
};

template< typename Iter >
struct NumLess : public binary_function<Iter, Iter, bool> {
    bool operator()( const Iter& t1, const Iter& t2 ) const { return t1->number < t2->number; }
};

void indices() {

    mytype v[] =    { { "me"    ,  0.0 }
                    , { "you"   ,  1.0 }
                    , { "them"  , -1.0 }
                    };
    mytype* vend = v + _countof(v);

    Index<mytype*, NameLess<mytype*> > byname( v, vend, NameLess<mytype*>() );
    Index<mytype*, NumLess <mytype*> > bynum ( v, vend, NumLess <mytype*>() );

    assert( byname.v[0] == v+0 );
    assert( byname.v[1] == v+2 );
    assert( byname.v[2] == v+1 );

    assert( bynum.v[0] == v+2 );
    assert( bynum.v[1] == v+0 );
    assert( bynum.v[2] == v+1 );

}

والجواب ltjax هي نهج العظيم - الذي يتم تنفيذه فعليا في zip_iterator دفعة و<لأ href = "http://www.boost.org/doc/libs/1_43_0/libs/iterator/doc/zip_iterator.html" يختلط = "نوفولو"> http://www.boost.org/doc/libs/1_43_0/libs/iterator/doc/zip_iterator.html

ووحزم معا في الصفوف (tuple) مهما كانت التكرارات التي تقدمها له.

ويمكنك بعد ذلك إنشاء وظيفة مقارنة بنفسك لفرز تستند إلى أي مجموعة من القيم مكرر في الصفوف (tuple) الخاص بك. لهذا السؤال، فإنه سيكون مجرد مكرر الأولى في الصفوف (tuple) الخاص بك.

وهناك ميزة جميلة من هذا النهج هو أنه يتيح لك للحفاظ على الذاكرة من كل متجاورة ناقلات الفردية (إذا كنت تستخدم ناقلات وهذا ما تريد). أنت أيضا لا تحتاج إلى تخزين ناقلات مؤشر منفصل من [إينتس].

ومتغير أكثر إحكاما قليلا من الإجابة xtofl لإذا كنت تبحث فقط تكرار خلال جميع ناقلات الخاصة بك على أساس من ناقلات keys واحد. إنشاء ناقلات التقليب واستخدام هذا المؤشر في ناقلات الأخرى.

#include <boost/iterator/counting_iterator.hpp>
#include <vector>
#include <algorithm>

std::vector<double> keys = ...
std::vector<double> values = ...

std::vector<size_t> indices(boost::counting_iterator<size_t>(0u), boost::counting_iterator<size_t>(keys.size()));
std::sort(begin(indices), end(indices), [&](size_t lhs, size_t rhs) {
    return keys[lhs] < keys[rhs];
});

// Now to iterate through the values array.
for (size_t i: indices)
{
    std::cout << values[i] << std::endl;
}

وهذا من شأنه أن يكون إضافة إلى الإجابة كونراد كما أنه نهجا لالبديل في نفس المكان من تطبيق ترتيب لناقلات. على أية حال منذ ان تحرير لا تمر سوف أضع هنا

وهنا هو البديل في نفس المكان مع تعقيد الوقت أعلى قليلا أن يرجع إلى عملية بدائية للتحقق منطقي. تعقيد مساحة إضافية لناقلات الذي يمكن أن يكون المترجم تنفيذ يعتمد الفضاء كفاءة. يمكن القضاء على تعقيد متجه إذا كان النظام نظرا نفسها يمكن تعديلها.

وهنا هو البديل في نفس المكان مع تعقيد الوقت أعلى قليلا أن يرجع إلى عملية بدائية للتحقق منطقي. تعقيد مساحة إضافية لناقلات الذي يمكن أن يكون المترجم تنفيذ يعتمد الفضاء كفاءة. يمكن القضاء على تعقيد متجه إذا كان من الممكن تعديل ترتيب معين نفسها. هذا هو مثال على ما تقوم به الخوارزمية. إذا كان النظام هو 3 0 4 1 2، وحركة العناصر كما يتضح من المؤشرات موقف سيكون 3 ---> 0؛ 0 ---> 1؛ 1 ---> 3؛ 2 ---> 4. 4 ---> 2

template<typename T>
struct applyOrderinPlace
{
void operator()(const vector<size_t>& order, vector<T>& vectoOrder)
{
vector<bool> indicator(order.size(),0);
size_t start = 0, cur = 0, next = order[cur];
size_t indx = 0;
T tmp; 

while(indx < order.size())
{
//find unprocessed index
if(indicator[indx])
{   
++indx;
continue;
}

start = indx;
cur = start;
next = order[cur];
tmp = vectoOrder[start];

while(next != start)
{
vectoOrder[cur] = vectoOrder[next];
indicator[cur] = true; 
cur = next;
next = order[next];
}
vectoOrder[cur] = tmp;
indicator[cur] = true;
}
}
};

وهنا هو تنفيذ بسيط نسبيا تستخدم رسم الخرائط مؤشر بين أمر وnames غير مرتبة التي سيتم استخدامها لتتناسب مع ages إلى names أمر:

void ordered_pairs()
{
    std::vector<std::string> names;
    std::vector<int> ages;

    // read input and populate the vectors
    populate(names, ages);

    // print input
    print(names, ages);

    // sort pairs
    std::vector<std::string> sortedNames(names);
    std::sort(sortedNames.begin(), sortedNames.end());

    std::vector<int> indexMap;
    for(unsigned int i = 0; i < sortedNames.size(); ++i)
    {
        for (unsigned int j = 0; j < names.size(); ++j)
        {
            if (sortedNames[i] == names[j]) 
            {
                indexMap.push_back(j);
                break;
            }
        }
    }
    // use the index mapping to match the ages to the names
    std::vector<int> sortedAges;
    for(size_t i = 0; i < indexMap.size(); ++i)
    {
        sortedAges.push_back(ages[indexMap[i]]);
    }

    std::cout << "Ordered pairs:\n";
    print(sortedNames, sortedAges); 
}

لمن أجل اكتمال، وهنا populate() الوظائف وprint():

void populate(std::vector<std::string>& n, std::vector<int>& a)
{
    std::string prompt("Type name and age, separated by white space; 'q' to exit.\n>>");
    std::string sentinel = "q";

    while (true)
    {
        // read input
        std::cout << prompt;
        std::string input;
        getline(std::cin, input);

        // exit input loop
        if (input == sentinel)
        {
            break;
        }

        std::stringstream ss(input);

        // extract input
        std::string name;
        int age;
        if (ss >> name >> age)
        {
            n.push_back(name);
            a.push_back(age);
        }
        else
        {
            std::cout <<"Wrong input format!\n";
        }
    }
}

وو:

void print(const std::vector<std::string>& n, const std::vector<int>& a)
{
    if (n.size() != a.size())
    {
        std::cerr <<"Different number of names and ages!\n";
        return;
    }

    for (unsigned int i = 0; i < n.size(); ++i)
    {
         std::cout <<'(' << n[i] << ", " << a[i] << ')' << "\n";
    }
}

وأخيرا، يصبح main():

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>

void ordered_pairs();
void populate(std::vector<std::string>&, std::vector<int>&);
void print(const std::vector<std::string>&, const std::vector<int>&);

//=======================================================================
int main()
{
    std::cout << "\t\tSimple name - age sorting.\n";
    ordered_pairs();
}
//=======================================================================
// Function Definitions...
**// C++ program to demonstrate sorting in vector
// of pair according to 2nd element of pair
#include <iostream>
#include<string>
#include<vector>
#include <algorithm>

using namespace std;

// Driver function to sort the vector elements
// by second element of pairs
bool sortbysec(const pair<char,char> &a,
              const pair<int,int> &b)
{
    return (a.second < b.second);
}

int main()
{
    // declaring vector of pairs
    vector< pair <char, int> > vect;

    // Initialising 1st and 2nd element of pairs
    // with array values
    //int arr[] = {10, 20, 5, 40 };
    //int arr1[] = {30, 60, 20, 50};
    char arr[] = { ' a', 'b', 'c' };
    int arr1[] = { 4, 7, 1 };

    int n = sizeof(arr)/sizeof(arr[0]);

    // Entering values in vector of pairs
    for (int i=0; i<n; i++)
        vect.push_back( make_pair(arr[i],arr1[i]) );

    // Printing the original vector(before sort())
    cout << "The vector before sort operation is:\n" ;
    for (int i=0; i<n; i++)
    {
        // "first" and "second" are used to access
        // 1st and 2nd element of pair respectively
        cout << vect[i].first << " "
             << vect[i].second << endl;

    }

    // Using sort() function to sort by 2nd element
    // of pair
    sort(vect.begin(), vect.end(), sortbysec);

    // Printing the sorted vector(after using sort())
    cout << "The vector after sort operation is:\n" ;
    for (int i=0; i<n; i++)
    {
        // "first" and "second" are used to access
        // 1st and 2nd element of pair respectively
        cout << vect[i].first << " "
             << vect[i].second << endl;
    }
    getchar();
    return 0;`enter code here`
}**

ومع C ++ 11 lambdas وخوارزميات STL بناء على اجابات من كونراد رودولف وغابرييل D'Antona:

template< typename T, typename U >
std::vector<T> sortVecAByVecB( std::vector<T> & a, std::vector<U> & b ){

    // zip the two vectors (A,B)
    std::vector<std::pair<T,U>> zipped(a.size());
    for( size_t i = 0; i < a.size(); i++ ) zipped[i] = std::make_pair( a[i], b[i] );

    // sort according to B
    std::sort(zipped.begin(), zipped.end(), []( auto & lop, auto & rop ) { return lop.second < rop.second; }); 

    // extract sorted A
    std::vector<T> sorted;
    std::transform(zipped.begin(), zipped.end(), std::back_inserter(sorted), []( auto & pair ){ return pair.first; }); 

    return sorted;
}
طلب

وهذا العدد الكبير من هذه المسألة، وجاء أحد إلى إجابة مرضية. هنا هو الأمراض المنقولة جنسيا :: نوع المساعد التي تمكن من فرز متجهين في وقت واحد، مع الأخذ بعين الاعتبار قيم ناقل واحد فقط. ويستند هذا الحل على العرف RadomIt (مكرر عشوائي)، ويعمل مباشرة على بيانات المتجه الأصلي، دون نسخ مؤقتة، بنية إعادة ترتيب أو مؤشرات إضافية:

C ++، ترتيب واحد متجه بناء على واحد آخر

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top