Вы можете использовать селектор css n-типа
h1 span:nth-of-type(2)
, т.е.
items = soup.select("h1 span:nth-of-type(2)")
Затем итерируйте список.
Если возможно только одно совпадение, то просто:
item = soup.select_one("h1 span:nth-of-type(2)")
print(item.text.strip())
К сожалению, линейное время - единственный способ сделать это:
iter i(d.begin());
advance (i,distance<ConstIter>(i,ci));
где iter и constIter являются подходящими typedefs, а d - контейнер, по которому вы перебираете.
Возможно, это не тот ответ, который вы хотели, а несколько связанный.
Полагаю, вы хотите изменить ситуацию где итератор указывает на. Самый простой способ сделать это - вместо этого const_cast вернуть возвращенную ссылку.
Что-то вроде этого
const_cast
Я считаю, что это преобразование не нужно в хорошо разработанной программе.
Если вам нужно сделать это - попробуйте изменить код.
В качестве обходного пути вы можете сделать следующее:
typedef std::vector< size_t > container_type;
container_type v;
// filling container code
container_type::const_iterator ci = v.begin() + 3; // set some value
container_type::iterator i = v.begin();
std::advance( i, std::distance< container_type::const_iterator >( v.begin(), ci ) );
Но я думаю, что иногда это преобразование невозможно, потому что ваши алгоритмы могут не иметь доступа к контейнеру.
Вы можете вычесть итератор begin () из const_iterator, чтобы получить позицию, на которую указывает const_iterator, а затем добавить начало () вернуться к этому, чтобы получить неконстантный итератор. Я не думаю, что это будет очень эффективно для нелинейных контейнеров, но для линейных, таких как вектор, это займет постоянное время.
vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(3);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
vector<int>::iterator it = v.begin() + (ci - v.begin());
cout << *it << endl;
*it = 20;
cout << *ci << endl;
РЕДАКТИРОВАТЬ : Это работает только для линейных контейнеров (произвольного доступа).
вы можете преобразовать свой указатель значения константного итератора в неконстантный указатель значения и использовать его непосредственно как-то так
vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
v.push_back(2);
vector<int>::const_iterator ci = v.begin() + 2;
cout << *ci << endl;
*const_cast<int*>(&(*ci)) = 7;
cout << *ci << endl;
In the answers to your previous post, there were a couple of people, me included, that recommended using const_iterators instead for non-performance related reasons. Readability, traceability from the design board to the code... Using const_iterators to provide mutating access to a non-const element is much worse than never using const_iterators at all. You are converting your code into something that only you will understand, with a worse design and a real maintainability pain. Using const just to cast it away is much worse than not using const at all.
If you are sure you want it, the good/bad part of C++ is that you can always get enough rope to hang yourself. If your intention is using const_iterator for performance issues, you should really rethink it, but if you still want to shoot your foot off... well C++ can provide your weapon of choice.
First, the simplest: if your operations take the arguments as const (even if internally apply const_cast) I believe it should work directly in most implementations (even if it is probably undefined behavior).
If you cannot change the functors, then you could tackle the problem from either side: provide a non-const iterator wrapper around the const iterators, or else provide a const functor wrapper around the non-const functors.
Iterator façade, the long road:
template <typename T>
struct remove_const
{
typedef T type;
};
template <typename T>
struct remove_const<const T>
{
typedef T type;
};
template <typename T>
class unconst_iterator_type
{
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename remove_const<
typename std::iterator_traits<T>::value_type
>::type value_type;
typedef value_type* pointer;
typedef value_type& reference;
unconst_iterator_type( T it )
: it_( it ) {} // allow implicit conversions
unconst_iterator_type& operator++() {
++it_;
return *this;
}
value_type& operator*() {
return const_cast<value_type&>( *it_ );
}
pointer operator->() {
return const_cast<pointer>( &(*it_) );
}
friend bool operator==( unconst_iterator_type<T> const & lhs,
unconst_iterator_type<T> const & rhs )
{
return lhs.it_ == rhs.it_;
}
friend bool operator!=( unconst_iterator_type<T> const & lhs,
unconst_iterator_type<T> const & rhs )
{
return !( lhs == rhs );
}
private:
T it_; // internal (const) iterator
};
Статья Скотта Мейера о предпочтении итераторов над const_iterators отвечает на этот вопрос. Ответ Visage - единственная безопасная альтернатива до C ++ 11, но на самом деле это постоянное время для хорошо реализованных итераторов произвольного доступа и линейное время для других.