Вы также можете построить парную метку, пары значений, используя pyplot.plot (после разбора их из строкового представления). (Протестировано с версиями matplotlib 1.2.0 и 1.3.1.)
Пример:
import datetime
import random
import matplotlib.pyplot as plt
# make up some data
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(12)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]
# plot
plt.plot(x,y)
# beautify the x-labels
plt.gcf().autofmt_xdate()
plt.show()
Результирующее изображение:
[/g2]
Вот то же самое, что и график рассеяния:
import datetime
import random
import matplotlib.pyplot as plt
# make up some data
x = [datetime.datetime.now() + datetime.timedelta(hours=i) for i in range(12)]
y = [i+random.gauss(0,1) for i,_ in enumerate(x)]
# plot
plt.scatter(x,y)
# beautify the x-labels
plt.gcf().autofmt_xdate()
plt.show()
Производит изображение, подобное этому:
Вы должны передать вектор по ссылке, чтобы избежать многократных копий, поэтому итератор гарантированно будет сравниваться с итераторами одного и того же вектора, а не с другими:
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it) {
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
int main(){
vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v, v.begin()); // ok
vector<int>::iterator it = v.begin();
auto v2{ v };
if (it == v.begin())
cout << "it = v.begin()" << endl;
if (it == v2.begin()) // causes crash
cout << "it =v2.begin()" << endl;
}
Когда вы звоните print
, вы передаете вектор по значению. Это означает, что он каждый раз создает совершенно новый вектор, но итератор все еще исходит из исходного вектора. Поскольку итератор происходит из другого вектора, тест it == ivec.end()
всегда будет неудачным.
Мы можем это исправить, просто передав ivec
константную ссылку:
void print(const std::vector<int>& ivec, std::vector<int>::const_iterator it)
{
if (it == ivec.end())
return;
std::cout << *it++ << std::endl;
print(ivec, it);
}
И код работает отлично!
void print(const std::vector<int> ivec, std::vector<int>::const_iterator it) {
Параметр ivec
передается по значению. Оба эти параметра передаются по значению. Передача по значению означает, что внутри функции это копий исходных параметров.
Ваш main()
вызывает эту рекурсивную функцию, передавая ей свой вектор и начальный итератор своего вектора. Однако, поскольку все параметры передаются по значению, каждая рекурсивная итерация функции сравнивает итератор с end()
совершенно другого вектора. Неопределенное поведение.
Вы, очевидно, забыли передать вектор по ссылке. Первый параметр должен быть const std::vector<int> &ivec
.
Нет необходимости передавать два аргумента функции печати. Если вектор нулевой длины, ничего не печатать.
Если вектор имеет длину 1, выведите этот элемент.
Если вектор имеет длину больше 1, выведите меньший вектор (рекурсивно), который не содержит последний символ, а затем напечатайте последний символ.
Да, это создаст копию вектора для каждой рекурсии, но я думаю, что для меня это больше похоже на рекурсию. Увеличение указателя на каждом цикле не похоже на рекурсию.
#include <iostream>
#include <vector>
void print(const std::vector<int> vec) {
if (!vec.size())
return;
else {
print(std::vector<int>(vec.begin(), vec.end() - 1));
std::cout << " " << *(vec.end() - 1);
}
}
int main(){
std::vector<int> v{
5, 7, 77, 23, 10, 81
};
print(v);
}