Стирание объектов из списка STL

require.s.contexts содержит личные данные обо всех контекстах, о которых знает RequireJS. Контекст по умолчанию, если вы не используете параметр конфигурации context, называется _, поэтому require.s.contexts._ содержит личные данные относительно контекста по умолчанию.

Поле registry данных контекста содержит карту которые временно хранят информацию о модуле. Модуль будет на этой карте после его запроса, но только до тех пор, пока он не будет загружен.

Поле defined содержит карту всех модулей, определенных в контексте. Вы могли бы получить доступ к нему напрямую, но нет никаких оснований для этого, поскольку require.defined(id) расскажет вам, является ли модуль, названный id, определенным в контексте, к которому принадлежит require. (Различные контексты получают разные экземпляры require, поэтому функция require знает, из какого контекста он произошел.)

19
задан Adam Pierce 2 February 2009 в 01:15
поделиться

6 ответов

Erase возвраты итератор указывающий на элемент после стертого:

std::list<MyClass>::iterator it = myList.begin();
while (it != myList.end())
{
  if(myCondition(*it))
  {
    myOtherList.push_back(*it);
    it = myList.erase(it);
  }
  else
  {
    ++it;
  }
}
34
ответ дан 30 November 2019 в 02:52
поделиться

Списки STL имеют интересную функцию: splice() метод позволяет Вам пагубно переместить элементы от одного списка до другого.

splice() работает в постоянное время, и не копирует элементы или выполняет любые бесплатные выделения/освобождение хранилища. Обратите внимание, что оба списка должны иметь тот же тип, и они должны быть отдельными экземплярами списка (не две ссылки на тот же список).

Вот пример того, как Вы могли использовать splice():

for(std::list<MyClass>::iterator it = myList.begin(); it != myList.end(); ) {
    if(myCondition(*it)) {
        std::list<MyClass>::iterator oldIt = it++;
        myOtherList.splice(myOtherList.end(), myList, oldIt);
    } else {
        ++it;
    }
}
7
ответ дан 30 November 2019 в 02:52
поделиться

Решение 1

template<typename Fwd, typename Out, typename Operation>
Fwd move_if(Fwd first, Fwd last, Out result, Operation op)
{
    Fwd swap_pos = first;
    for( ; first != last; ++first ) {
        if( !op(*first) ) *swap_pos++ = *first;
        else *result++ = *first;
    }
    return swap_pos;
}

Идея проста. То, что Вы хотите сделать, , удаляют элементы из одного контейнера и размещают их в другого, если предикат верен. Поэтому возьмите код std::remove() алгоритм, который уже делает удалить часть и адаптирует ее к Вашим дополнительным потребностям. В коде выше я добавил else строка для копирования элемента, когда предикат верен.

Уведомление, что, потому что мы используем эти std::remove() код, алгоритм на самом деле не уменьшает входной контейнер. Это действительно возвращает обновленный конечный итератор входного контейнера, хотя, таким образом, можно просто использовать это и игнорировать дополнительные элементы. Используйте эти , стирание - удаляет идиому , если Вы действительно хотите уменьшить входной контейнер.

Решение 2

template<typename Bidi, typename Out, typename Operation>
Bidi move_if(Bidi first, Bidi last, Out result, Operation op)
{
    Bidi new_end = partition(first, last, not1(op));
    copy(new_end, last, result);
    return new_end;
}

второй подход использует STL для реализации алгоритма. Я лично нахожу это более читаемым, чем первое решение, но это имеет два недостатка: Во-первых, это требует более - мощные двунаправленные итераторы для входного контейнера, а не вперед итераторы, которые мы использовали в первом решении. Во-вторых, и это, может или может не быть проблема для Вас, контейнеры, как гарантируют, не будут иметь то же упорядочивание как перед вызовом к std::partition(). Если Вы хотите поддержать упорядочивание, замена, которые звонят с вызовом в std::stable_partition(). std::stable_partition() могло бы быть немного медленнее, но это имеет ту же сложность во время выполнения как std::partition().

Так или иначе: Вызов Функции

list<int>::iterator p = move_if(l1.begin(), l1.end(),
                                back_inserter(l2),
                                bind2nd(less<int>(), 3));

Заключительные Комментарии

При написании кода я встретился с дилеммой: что move_if() должен возвратить алгоритм? С одной стороны, алгоритм должен возвратить итератор, указывающий на новое конечное положение входного контейнера, таким образом, вызывающая сторона может использовать стирание - удаляют идиому для уменьшения контейнера. Но с другой стороны алгоритм должен возвратить положение конца контейнера результата, потому что иначе это могло быть дорого, чтобы вызывающая сторона нашла его. В первом решении result итератор указывает на это положение, когда алгоритм заканчивается, в то время как во втором решении это - итератор, возвращенный [1 112], который указывает на это положение. Я мог возвратить пару итераторов, но ради создания вещей, простых, я просто возвращаю один из итераторов.

4
ответ дан 30 November 2019 в 02:52
поделиться

Другая попытка:

for(std::list<MyClass>::iterator it = myList.begin(); it != myList.end; ) {
    std::list<MyClass>::iterator eraseiter = it;
    ++it;
    if(myCondition(*eraseiter)) {
        myOtherList.push_back(*eraseiter);
        myList.erase(eraseiter);
    }
}
0
ответ дан 30 November 2019 в 02:52
поделиться
std::list<MyClass>::iterator endMatching =
    partition(myList.begin(), myList.end(), myCondition);
myOtherList.splice(myOtherList.begin(), myList, endMatching, myList.end());

Указание, которое раздел () дает Вам достаточно для различения соответствующих объектов от не соответствия. (список:: соединение встык () является дешевым однако)

, Видят следующий код конкретного случая, вдохновленного от Теперь для удаления элементов, которые соответствуют предикату?

#include <iostream>
#include <iterator>
#include <list>
#include <string>
#include <algorithm>
#include <functional>

using namespace std;

class CPred : public unary_function<string, bool>
{
public:
        CPred(const string& arString)
                :mString(arString)
        {
        }

        bool operator()(const string& arString) const
        {
                return (arString.find(mString) == std::string::npos);
        }
private:
        string mString;
};

int main()
{
        list<string> Strings;

        Strings.push_back("213");
        Strings.push_back("145");
        Strings.push_back("ABC");
        Strings.push_back("167");
        Strings.push_back("DEF");

        cout << "Original list" << endl;
        copy(Strings.begin(), Strings.end(),ostream_iterator<string>(cout,"\n"));

        CPred Pred("1");

        // Linear. Exactly last - first applications of pred, and at most (last - first)/2 swaps. 
        list<string>::iterator end1 =
        partition(Strings.begin(), Strings.end(), Pred);

        list<string> NotMatching;

        // This function is constant time. 
        NotMatching.splice(NotMatching.begin(),Strings, Strings.begin(), end1); 

        cout << "Elements matching with 1" << endl;
        copy(Strings.begin(), Strings.end(), ostream_iterator<string>(cout,"\n"));

        cout << "Elements not matching with 1" << endl;
        copy(NotMatching.begin(), NotMatching.end(), ostream_iterator<string>(cout,"\n"));

        return 0;
}
1
ответ дан 30 November 2019 в 02:52
поделиться
template <typename ForwardIterator, typename OutputIterator, typename Predicate>
void splice_if(ForwardIterator begin, ForwardIterator end, OutputIterator out, Predicate pred)
{
    ForwardIterator it = begin;
    while( it != end )
    {
        if( pred(*it) )
        {
            *begin++ = *out++ = *it;
        }
        ++it;
    }
    return begin;
}

myList.erase( 
    splice_if( myList.begin(), myList.end(), back_inserter(myOutputList),
        myCondition
    ),
    myList.end()
)
0
ответ дан 30 November 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: