Это довольно простая работа, и awk
- действительно нужный инструмент:
awk 'NR==FNR{a[$1]=$2;next}{print [110],a[$1]}' fileb filea
или
awk 'NR==FNR{a[$1]=$2;next}{print $1,$2,a[$1]}' fileb filea
Но, пожалуйста, покажите свои собственные усилия в следующий раз, как Вы искали / пытались и не смогли.
Помоги себе, помоги другим помочь тебе.
К сожалению std :: queue
«адаптирует» функцию, известную как push_back
, только для push
, что означает, что стандартный back_insert_iterator
не работает.
Вероятно, самый простой способ (хотя концептуально уродливый) - это адаптировать адаптер контейнера с короткоживущим адаптером адаптера контейнера [sic] (эй!), Который живет до тех пор, пока не будет вставить итератор.
template<class T>
class QueueAdapter
{
public:
QueueAdapter(std::queue<T>& q) : _q(q) {}
void push_back(const T& t) { _q.push(t); }
private:
std::queue<T>& _q;
};
Используется так:
std::queue<int> qi;
QueueAdapter< std::queue<int> > qiqa( qi );
std::copy( v.begin(), v.end(), std::back_inserter( qiqa ) );
Я почти уверен, что это просто не сработает - очередь предоставляет push
, но итератор вставки предполагает использовать push_front
или push_back
. Нет никакой реальной причины, по которой вы не могли бы написать свое push_insert_iterator
(или любое другое имя, которое вы предпочитаете), но это немного болезненно ...
insert_iterator
и back_insert_iterator
работают только с контейнерами (или адаптерами) с (соответственно) методами insert
и push_back
- очередь
их не имеет. Вы можете написать свой собственный итератор, смоделированный на их основе, примерно так:
template <typename Container>
class push_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
public:
explicit push_iterator(Container &c) : container(c) {}
push_iterator &operator*() {return *this;}
push_iterator &operator++() {return *this;}
push_iterator &operator++(int) {return *this;}
push_iterator &operator=(typename Container::const_reference value)
{
container.push(value);
return *this;
}
private:
Container &container;
};
Если такая вещь еще не существует, но я почти уверен, что это не так.
std :: queue
не контейнер в смысле STL, это контейнер адаптер с очень ограниченной функциональностью. Для того, что вам, кажется, нужно, либо std :: vector
, либо std :: deque
(«двусторонняя очередь, которая является« настоящим контейнером ») кажется правильным выбором.
Очередь не допускает итерацию по своим элементам.
Из SGI STL Docs :
Очередь - это адаптер, который предоставляет ограниченное подмножество контейнера функциональность Очередь - это "первый в структура данных «первым вышел» (FIFO). 1 То есть элементы добавляются в в конце очереди и может быть удален спереди; Q.front () - это элемент, который был добавлен в очередь по крайней мере недавно. Очередь не позволяет итерация по его элементам. [2]
Вы можете выполнить эту работу, но вы не можете использовать insert_iterator
. Вам нужно будет написать что-то вроде queue_inserter
, представляющее интерфейс итератора.
Обновление Я не мог с собой поделать и решил попробовать реализовать нужный итератор. Вот результаты:
template< typename T, typename U >
class queue_inserter {
queue<T, U> &qu;
public:
queue_inserter(queue<T,U> &q) : qu(q) { }
queue_inserter<T,U> operator ++ (int) { return *this; }
queue_inserter<T,U> operator * () { return *this; }
void operator = (const T &val) { qu.push(val); }
};
template< typename T, typename U >
queue_inserter<T,U> make_queue_inserter(queue<T,U> &q) {
return queue_inserter<T,U>(q);
}
Это отлично работает для таких функций:
template<typename II, typename OI>
void mycopy(II b, II e, OI oi) {
while (b != e) { *oi++ = *b++; }
}
Но это не работает с копией STL, потому что STL глуп.
Что вам нужно, так это push_inserter
(то есть устройство вставки, которое выполняет push
es в очередь). Насколько мне известно, такого итератора в STL нет. Что я обычно делаю, так это, к сожалению, возвращаюсь к старому доброму циклу for.
Если у вас хватит смелости, вы можете создать свой собственный итератор, что-нибудь в этом роде:
template <typename Container>
class push_insert_iterator
{
public:
typedef Container container_type;
typedef typename Container::value_type value_type;
explicit push_insert_iterator(container_type & c)
: container(c)
{} // construct with container
push_insert_iterator<container_type> & operator=(const value_type & v)
{
//push value into the queue
container.push(v);
return (*this);
}
push_insert_iterator<container_type> & operator*()
{
return (*this);
}
push_insert_iterator<container_type> & operator++()
{
// Do nothing
return (*this);
}
push_insert_iterator<container_type> operator++(int)
{
// Do nothing
return (*this);
}
protected:
container_type & container; // reference to container
};
template <typename Container>
inline push_insert_iterator<Container> push_inserter(Container & c)
{
return push_insert_iterator<Container>(c);
}
Это всего лишь черновик, но идея у вас есть. Работает с любым контейнером (или, ну, контейнерными адаптерами) с методом push
(например, queue
, stack
).
std :: queue
не является одним из основных контейнеров в STL. Это контейнерный адаптер, созданный с использованием одного из базовых контейнеров STL (в данном случае одного из последовательных контейнеров либо std :: vector
std :: deque
, либо std :: list
). Он разработан специально для поведения FIFO и не обеспечивает случайную вставку в заданный итератор, который требуется для работы insert_iterator
. Следовательно, будет невозможно использовать такую очередь.
Самый простой способ, который я мог придумать, - это:
class PushFunctor
{
public:
PushFunctor(std::queue<int>& q) : myQ(q)
{
}
void operator()(int n)
{
myQ.push(n);
}
private:
std::queue<int>& myQ;
};
И использовать его так:
queue<int> q;
PushFunctor p(q);
std::for_each(v.begin(), v.end(), p);
In this simple case, you can write:
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
queue<int, vector<int> > q(v);
This will make a copy of the vector
and use it as the underlying container of the queue
.
Of course, this approach won't work if you need to enqueue things after the queue has been constructed.