Это расширение для двух ответов, уже представленных выше, поскольку производительность во время исполнения показалась темой комментариев. Я добавил бы его в качестве комментариев, но у меня еще нет этой привилегии.
Я тестировал 2 реализации для производительности во время исполнения с использованием Visual Studio 2015:
Использование stringstream:
std::stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
Использование accumulate:
std::string result = std::accumulate(std::next(vec.begin()), vec.end(),
std::to_string(vec[0]),
[&delimiter](std::string& a, uint8_t b) {
return a + delimiter+ std::to_string(b);
});
return result;
Производительность выполнения сборки сборки была близка к парам тонкостей.
Реализация накопления была немного быстрее (20-50 мс, ~ 10-30% от общей продолжительности (~ 180 мс) на 1000 итераций по 256-элементному вектору). Однако реализация accumulate
была только быстрее, когда параметр a
для функции лямбда был передан по ссылке. Передача параметра a
по значению привела к аналогичной разнице во времени во время реализации stringstream
. Реализация accumulate
также улучшилась, когда возвратная строка была возвращена напрямую, а не назначена локальной переменной, которая была немедленно возвращена. YMMV с другими компиляторами C ++.
Сборка Debug была в 5-10 раз медленнее с использованием accumulate
, поэтому я думаю, что добавление дополнительной строки, отмеченное в нескольких комментариях выше, разрешено оптимизатором.
Я искал конкретную реализацию, используя vector
значений uint8_t
. Полный тестовый код:
#include <vector>
#include <iostream>
#include <sstream>
#include <numeric>
#include <chrono>
using namespace std;
typedef vector<uint8_t> uint8_vec_t;
string concat_stream(const uint8_vec_t& vec, string& delim = string(" "));
string concat_accumulate(const uint8_vec_t& vec, string& delim = string(" "));
string concat_stream(const uint8_vec_t& vec, string& delimiter)
{
stringstream result;
auto it = vec.begin();
result << (unsigned short)*it++;
for (; it != vec.end(); it++) {
result << delimiter;
result << (unsigned short)*it;
}
return result.str();
}
string concat_accumulate(const uint8_vec_t& vec, string& delimiter)
{
return accumulate(next(vec.begin()), vec.end(),
to_string(vec[0]),
[&delimiter](string& a, uint8_t b) {
return a + delimiter + to_string(b);
});
}
int main()
{
const int elements(256);
const int iterations(1000);
uint8_vec_t test(elements);
iota(test.begin(), test.end(), 0);
int i;
auto stream_start = chrono::steady_clock::now();
string join_with_stream;
for (i = 0; i < iterations; ++i) {
join_with_stream = concat_stream(test);
}
auto stream_end = chrono::steady_clock::now();
auto acc_start = chrono::steady_clock::now();
string join_with_acc;
for (i = 0; i < iterations; ++i) {
join_with_acc = concat_accumulate(test);
}
auto acc_end = chrono::steady_clock::now();
cout << "Stream Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(stream_end - stream_start).count() << " ms" << endl;
cout << " result: " << join_with_stream << endl;
cout << "Accumulate Results:" << endl;
cout << " elements: " << elements << endl;
cout << " iterations: " << iterations << endl;
cout << " runtime: " << chrono::duration<double, milli>(acc_end - acc_start).count() << " ms" << endl;
cout << " result:" << join_with_acc << endl;
return 0;
}
Обновите несколько лет спустя: Python 3.6 теперь поддерживает PEP515 , и поэтому вы можете использовать _ для улучшения удобочитаемости с плавающей и целочисленной литералами.
Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 1_1000
11000
>>>
Для справки по истории, вы можете посмотреть на лексический анализ для строгих определений python2.7 , python3.5 ...
Для python3.6.0a2 и ранее вы должен получить сообщение об ошибке, подобное:
Python 3.6.0a2 (v3.6.0a2:378893423552, Jun 13 2016, 14:44:21)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1_000
File "<stdin>", line 1
1_000
^
SyntaxError: invalid syntax
>>> amount = 10_000_000.0
File "<stdin>", line 1
amount = 10_000_000.0
^
SyntaxError: invalid syntax
В Python такой функции нет, но было предложено интегрировать ее в будущем.
Вы можете увидеть предложение в PEP515 .
В настоящее время в Python нет разделителя тысяч, но вы можете использовать модуль locale
для преобразования строки с такими разделителями в int:
import locale
locale.setlocale(locale.LC_ALL, '')
locale.atoi("1,000,000")
Самое близкое, что я видел в python, это 12 * 1000 * 1000
, что не идеально, но может быть полезно, если требуется 12000000
. Однако, хотя в C они эквивалентны, поскольку во время компиляции он преобразует оба значения в одно и то же, python может не разделять эту оптимизацию.
float
или int
...
– mgilson
2 July 2016 в 00:17
dis.dis(lambda : 100 * 200 * 300)
– mgilson
2 July 2016 в 00:18
x * 100 * 1000 * 1000
, то он не будет сбрасываться (потому что x * 100
может не возвращать int
, если x
не является int
). Но 100 * 1000 * 1000 * x
складывается, потому что оценка слева направо работает с известными константами.
– ShadowRanger
2 July 2016 в 00:34