push back векторы значения в вектор - для цикла - загрузка процессора [дубликат]

вы можете использовать следующую вспомогательную функцию:

function content(divSelector, value) {
    document.querySelector(divSelector).innerHTML = value;
}

content('#content',"whatever");

Где #content должен быть прав Селектор CSS

Вот рабочий пример .


Дополнительно - сегодня (2018.07.01) Я сделал сравнение скорости для jQuery и чистых js-решений (MacOs High Sierra 10.13.3 на Chrome 67.0.3396.99 (64-разрядная версия) , Safari 11.0.3 (13604.5.6), Firefox 59.0.2 (64-разрядная версия)):

document.getElementById("content").innerHTML = "whatever"; // pure JS
$('#content').html('whatever');                            // jQuery

Решение jquery было медленнее, чем чистое решение js: 69% на firefox, 61% на сафари, 56% на хром. Самый быстрый браузер для чистых js был firefox с 560M операций в секунду, второй - сафари 426M, а самым медленным был хром 122M.

Итак, победители - это чистые js и firefox (в 3 раза быстрее, чем хром!)

Вы можете проверить его на своем компьютере: https://jsperf.com/js-jquery-html-content-change

507
задан emlai 9 February 2016 в 00:04
поделиться

17 ответов

Если вы используете C ++ 11 и хотите переместить элементы, а не просто их копировать, вы можете использовать std :: move_iterator ( http://en.cppreference.com/w/cpp/iterator / move_iterator ) вместе со вставкой (или копией):

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<int> dest{1,2,3,4,5};
  std::vector<int> src{6,7,8,9,10};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  // Print out concatenated vector.
  std::copy(
      dest.begin(),
      dest.end(),
      std::ostream_iterator<int>(std::cout, "\n")
    );

  return 0;
}

Это не будет более эффективным для примера с int, поскольку перемещение их неэффективно, чем копирование, но для структура данных с оптимизированными ходами, она может избежать копирования ненужного состояния:

#include <vector>
#include <iostream>
#include <iterator>

int main(int argc, char** argv) {
  std::vector<std::vector<int>> dest{{1,2,3,4,5}, {3,4}};
  std::vector<std::vector<int>> src{{6,7,8,9,10}};

  // Move elements from src to dest.
  // src is left in undefined but safe-to-destruct state.
  dest.insert(
      dest.end(),
      std::make_move_iterator(src.begin()),
      std::make_move_iterator(src.end())
    );

  return 0;
}

После перемещения элемент src остается в неопределенном, но безопасном для разрушения состоянии, а его прежние элементы были переданы напрямую к новому элементу dest в конце.

121
ответ дан Alex 22 August 2018 в 02:14
поделиться
  • 1
    Метод std :: make_move_iterator () помог мне при попытке конкатенации std :: vectors из std :: unique_ptr. – Knitschi 27 December 2014 в 14:43

Если вы заинтересованы в надежной гарантии исключения (когда конструктор копирования может генерировать исключение):

template<typename T>
inline void append_copy(std::vector<T>& v1, const std::vector<T>& v2)
{
    const auto orig_v1_size = v1.size();
    v1.reserve(orig_v1_size + v2.size());
    try
    {
        v1.insert(v1.end(), v2.begin(), v2.end());
    }
    catch(...)
    {
        v1.erase(v1.begin() + orig_v1_size, v1.end());
        throw;
    }
}

Аналогичный append_move с сильной гарантией не может быть реализован вообще, если конструктор перемещения векторного элемента может бросить (что маловероятно, но все же).

4
ответ дан AlexT 22 August 2018 в 02:14
поделиться
  • 1
    Невозможно ли бросить v1.erase(...? – camelCase 12 October 2015 в 15:33
  • 2
    insert уже справляется с этим. Кроме того, этот вызов erase эквивалентен resize. – Potatoswatter 27 December 2016 в 08:02

Вы должны использовать vector :: insert

v1.insert(v1.end(), v2.begin(), v2.end());
7
ответ дан Boris 22 August 2018 в 02:14
поделиться

Если то, что вы ищете, это способ добавить вектор к другому после создания, vector::insert - ваш лучший выбор, как было сказано несколько раз, например:

vector<int> first = {13};
const vector<int> second = {42};

first.insert(first.end(), second.cbegin(), second.cend());

К сожалению, нет способа построить const vector<int>, как указано выше, вы должны построить, а затем insert.


Если то, что вы действительно ищете, является контейнером чтобы удерживать конкатенацию этих двух vector<int> s, может быть что-то более доступное для вас, если:

  1. Ваш vector содержит примитивы
  2. Ваши содержащиеся примитивы размером 32 бит или меньше
  3. Вы хотите контейнер const

Если все это верно, я бы предложил использовать basic_string , который char_type соответствует размеру примитива, содержащегося в вашем vector. Вы должны включить в свой код static_assert , чтобы подтвердить, что эти размеры остаются неизменными:

static_assert(sizeof(char32_t) == sizeof(int));

С этим удерживанием true вы можете просто сделать:

const u32string concatenation = u32string(first.cbegin(), first.cend()) + u32string(second.cbegin(), second.cend());

Для получения дополнительной информации о различиях между string и vector вы можете посмотреть здесь: https://stackoverflow.com/a/35558008/2642059

Для живой пример этого кода вы можете посмотреть здесь: http://ideone.com/7Iww3I

0
ответ дан Community 22 August 2018 в 02:14
поделиться

Вот общее решение с использованием семантики перемещения C ++ 11:

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, const std::vector<T>& rhs)
{
    if (lhs.empty()) return rhs;
    if (rhs.empty()) return lhs;
    std::vector<T> result {};
    result.reserve(lhs.size() + rhs.size());
    result.insert(result.cend(), lhs.cbegin(), lhs.cend());
    result.insert(result.cend(), rhs.cbegin(), rhs.cend());
    return result;
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, const std::vector<T>& rhs)
{
    lhs.insert(lhs.cend(), rhs.cbegin(), rhs.cend());
    return std::move(lhs);
}

template <typename T>
std::vector<T> concat(const std::vector<T>& lhs, std::vector<T>&& rhs)
{
    rhs.insert(rhs.cbegin(), lhs.cbegin(), lhs.cend());
    return std::move(rhs);
}

template <typename T>
std::vector<T> concat(std::vector<T>&& lhs, std::vector<T>&& rhs)
{
    if (lhs.empty()) return std::move(rhs);
    lhs.insert(lhs.cend(), std::make_move_iterator(rhs.begin()), std::make_move_iterator(rhs.end()));
    return std::move(lhs);
}

Обратите внимание, что это отличается от append до vector.

2
ответ дан Daniel 22 August 2018 в 02:14
поделиться

С C ++ 11 я предпочел бы добавить вектор b к a:

std::move(b.begin(), b.end(), std::back_inserter(a));

, когда a и b не перекрываются, а b не идет которые будут использоваться больше.

33
ответ дан Deqing 22 August 2018 в 02:14
поделиться
  • 1
    Неопределенное поведение, если на самом деле это b (это нормально, если вы знаете, что этого никогда не будет, но стоит знать в коде общего назначения). – Martin Bonner 20 November 2015 в 14:53
  • 2
    @MartinBonner Спасибо, что упомянули об этом. Вероятно, я должен вернуться к старому insert способу, который безопаснее. – Deqing 1 February 2016 в 04:31
  • 3
    просто добавьте следующую строку заголовка begin: #include & lt; iterator & gt; – Manohar Reddy Poreddy 10 September 2016 в 12:07
  • 4
    Ах, ДРУГОЙ std :: move. Совсем смущает первый раз, когда вы это видите. – xaxxon 16 September 2016 в 02:52
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2 = {11, 12, 13, 14, 15};
copy(v2.begin(), v2.end(), back_inserter(v1));
3
ответ дан instance 22 August 2018 в 02:14
поделиться
std::vector<int> first;
std::vector<int> second;

first.insert(first.end(), second.begin(), second.end());
31
ответ дан James Curran 22 August 2018 в 02:14
поделиться

С диапазоном v3 у вас может быть ленивая конкатенация:

ranges::view::concat(v1, v2)

Демо .

4
ответ дан Jarod42 22 August 2018 в 02:14
поделиться

Я бы использовал функцию insert , что-то вроде:

vector<int> a, b;
//fill with data
b.insert(b.end(), a.begin(), a.end());
120
ответ дан Jon Cage 22 August 2018 в 02:14
поделиться
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
550
ответ дан Robert Gamble 22 August 2018 в 02:14
поделиться
  • 1
    Я бы добавил только код, чтобы сначала получить количество элементов, которые есть у каждого вектора, и установить vector1 как тот, который держит наибольший. Если вы это сделаете, вы делаете много ненужного копирования. – Joe Pineda 14 October 2008 в 17:11
  • 2
    У меня есть вопрос. Будет ли это работать, если vector1 и vector2 являются одинаковыми векторами? – Alexander Rafferty 17 July 2011 в 10:36
  • 3
    Если вы связываете несколько векторов с одним, полезно ли сначала называть reserve на векторе назначения? – Faheem Mitha 5 February 2012 в 01:07
  • 4
    @AlexanderRafferty: Только если vector1.capacity() >= 2 * vector1.size(). Что является нетипичным, если вы не вызвали std::vector::reserve(). В противном случае вектор перераспределит, аннулирует итераторы, переданные как параметры 2 и 3. – Drew Dormann 21 June 2012 в 21:30
  • 5
    Слишком плохо, что в стандартной библиотеке нет более сжатого выражения. .concat или += или что-то – nmr 14 October 2016 в 23:32

Или вы можете использовать:

std::copy(source.begin(), source.end(), std::back_inserter(destination));

Этот шаблон полезен, если два вектора не содержат точно такого же типа, потому что вы можете использовать что-то вместо std :: back_inserter для преобразования от одного типа к другому.

71
ответ дан Roger Lipscombe 22 August 2018 в 02:14
поделиться
  • 1
    метод копирования не является таким хорошим способом. Он будет вызывать push_back несколько раз, что означает, что если нужно добавить много элементов, это может означать множественные перераспределения. лучше использовать вставку, поскольку векторная реализация может сделать некоторую оптимизацию, чтобы избежать перераспределения. он может зарезервировать память перед началом копирования – Yogesh Arora 22 March 2010 в 14:16
  • 2
    @Yogesh: предоставлено, но нет ничего, что помешало бы вам сначала называть reserve. Иногда полезно использовать std::copy, если вы хотите использовать что-то другое, кроме back_inserter. – Roger Lipscombe 22 March 2010 в 19:36
  • 3
    Когда вы говорите «множественные распределения», это правда, но количество распределений в худшем журнале (количество добавленных записей), что означает, что стоимость добавления записи является постоянной в количестве добавленных записей. (В принципе, не беспокойтесь об этом, если профилирование не показывает, что вам нужен запас). – Martin Bonner 20 November 2015 в 14:55
  • 4
    Вместо этого вы можете использовать std :: transform. – Martin Broadhurst 7 February 2016 в 17:01
  • 5
    копия отстойная, даже с запасом. vector :: insert будет избегать всех проверок: quick-bench.com/bLJO4OfkAzMcWia7Pa80ynwmAIA – Denis Yaroshevskiy 29 July 2018 в 16:31

Я предпочитаю тот, который уже упоминался:

a.insert(a.end(), b.begin(), b.end());

Но если вы используете C ++ 11, существует еще один общий способ:

a.insert(std::end(a), std::begin(b), std::end(b));

Кроме того, это не вопрос, но рекомендуется использовать reserve перед добавлением для повышения производительности. И если вы конкатенируете вектор с собой, не оставляя его, он всегда должен reserve.


Итак, в основном, что вам нужно:

template <typename T>
void Append(std::vector<T>& a, const std::vector<T>& b)
{
    a.reserve(a.size() + b.size());
    a.insert(a.end(), b.begin(), b.end());
}
19
ответ дан ST3 22 August 2018 в 02:14
поделиться

Добавьте этот файл в файл заголовка:

template <typename T> vector<T> concat(vector<T> &a, vector<T> &b) {
    vector<T> ret = vector<T>();
    copy(a.begin(), a.end(), back_inserter(ret));
    copy(b.begin(), b.end(), back_inserter(ret));
    return ret;
}

и используйте его следующим образом:

vector<int> a = vector<int>();
vector<int> b = vector<int>();

a.push_back(1);
a.push_back(2);
b.push_back(62);

vector<int> r = concat(a, b);

r будет содержать [1,2,62]

2
ответ дан Stepan Yakovenko 22 August 2018 в 02:14
поделиться
  • 1
    Не знаю, почему это было отклонено. Возможно, это не самый эффективный способ сделать это, но это не так и эффективно. – leeor_net 19 June 2016 в 19:11

Честно говоря, вы могли бы быстро объединить два вектора путем копирования элементов из двух векторов в другой или просто добавить один из двух векторов !.

Метод 1: Назначить новый вектор с его размером представляет собой сумму двух исходных размеров векторов.

vector<int> concat_vector = vector<int>();
concat_vector.setcapacity(vector_A.size() + vector_B.size());
// Loop for copy elements in two vectors into concat_vector

Способ 2: добавить вектор A, добавив / вставка элементов вектора B.

// Loop for insert elements of vector_B into vector_A with insert() 
function: vector_A.insert(vector_A .end(), vector_B.cbegin(), vector_B.cend());
0
ответ дан Trevor Hickey 22 August 2018 в 02:14
поделиться

Общий прирост производительности для конкатенации - проверка размера векторов. И объедините / вставьте меньший с большим.

//vector<int> v1,v2;
if(v1.size()>v2.size()){
    v1.insert(v1.end(),v2.begin(),v2.end());
}else{
    v1.insert(v2.end(),v1.begin(),v1.end());
}
1
ответ дан Vikramjit Roy 22 August 2018 в 02:14
поделиться

Вы можете подготовить свой собственный шаблон для оператора +:

template <typename T> 
inline T operator+(const T & a, const T & b)
{
    T res = a;
    res.insert(res.end(), b.begin(), b.end());
    return res;
}

. Следующее - просто используйте +:

vector<int> a{1, 2, 3, 4};
vector<int> b{5, 6, 7, 8};
for (auto x: a + b)
    cout << x << " ";
cout << endl;

В этом примере приведены результаты:

1 2 3 4 5 6 7 8
1
ответ дан Vladimir U. 22 August 2018 в 02:14
поделиться
Другие вопросы по тегам:

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