Jaki jest najskuteczniejszy sposób uzyskania indeksu iteratora std:: vector?
Iteruję nad wektorem i potrzebuję indeksu, na który aktualnie wskazuje iterator. AFAIK można to zrobić na dwa sposoby:
it - vec.begin()
std::distance(vec.begin(), it)
Jakie są plusy i minusy tych metod?
10 answers
Wolałbym it - vec.begin()
właśnie z przeciwnego powodu podanego przez naveena: więc nie skompilowałby się, jeśli zmienisz wektor w listę. Jeśli zrobisz to podczas każdej iteracji, możesz łatwo przekształcić algorytm O(n) W algorytm O(N^2).
Inną opcją, jeśli nie przeskakujesz w kontenerze podczas iteracji, byłoby zachowanie indeksu jako licznika drugiej pętli.
Uwaga: {[1] } jest potoczną nazwą iteratora kontenera, std::container_type::iterator it;
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-30 22:35:44
Wolałbym std::distance(vec.begin(), it)
, ponieważ pozwoli mi to na zmianę kontenera bez żadnych zmian kodu. Na przykład, jeśli zdecydujesz się użyć std::list
zamiast std::vector
, który nie zapewnia losowego iteratora dostępu, Twój kod nadal będzie kompilowany. Ponieważ STD:: distance wybiera optymalną metodę w zależności od cech iteratora, nie będziesz mieć również żadnego pogorszenia wydajności.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 07:46:20
UncleBens i Naveen pokazali, że istnieją dobre powody dla obu. Które z nich jest "lepsze" zależy od tego, jakie zachowanie chcesz: czy chcesz zagwarantować zachowanie w stałym czasie, czy chcesz, aby w razie potrzeby spaść z powrotem do czasu liniowego?
it - vec.begin()
zajmuje stały czas, ale operator -
jest definiowany tylko na iteratorach dostępu losowego, więc kod nie będzie kompilowany z iteratorami listy, na przykład.
std::distance(vec.begin(), it)
działa dla wszystkich typów iteratorów, ale będzie działać tylko w czasie stałym jeśli jest używany na iteratorach dostępu losowego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 12:21:19
Podoba mi się ten: it - vec.begin()
, ponieważ dla mnie wyraźnie mówi "odległość od początku". Z iteratorami jesteśmy przyzwyczajeni do myślenia w kategoriach arytmetyki, więc znak -
jest tutaj najczystszym wskaźnikiem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 07:46:12
Jeśli masz już ograniczony / zakodowany na twardo algorytm do używania tylko std::vector::iterator
i std::vector::iterator
, nie ma znaczenia, która metoda zostanie użyta. Twój algorytm jest już skonkretyzowany poza punktem, w którym wybór jednego z nich może zrobić dowolną różnicę. Oboje robią dokładnie to samo. To tylko kwestia osobistych preferencji. Osobiście użyłbym wyraźnego odejmowania.
Jeśli natomiast chcesz zachować wyższy stopień ogólności w algorytmie, mianowicie, aby umożliwić możliwość, że pewnego dnia w przyszłości może być zastosowana do innego typu iteratora, wtedy najlepsza metoda zależy od twoich intencji. To zależy od tego, jak restrykcyjne chcesz być w odniesieniu do typu iteratora, który może być używany tutaj.
Jeśli użyjesz jawnego odejmowania, Twój algorytm będzie ograniczony do raczej wąskiej klasy iteratorów: iteratorów o dostępie losowym. (To jest to, co dostajesz teraz z
std::vector
)Jeśli używasz
distance
, algorytm będzie obsługiwał znacznie szerszą klasę iteratorów: Iteratory wejściowe.
Oczywiście, obliczanie distance
dla iteratorów bez dostępu losowego jest w ogólnym przypadku operacją nieefektywną (podczas gdy, PONOWNIE, dla iteratorów z dostępem losowym jest równie wydajne jak odejmowanie). To do ciebie należy decyzja, czy twój algorytm ma sens dla iteratorów bez dostępu losowego, pod względem wydajności. Wynikająca z tego utrata wydajności jest niszczycielska do tego stopnia, że Twój algorytm jest całkowicie bezużyteczne, to lepiej trzymać się odejmowania, tym samym zakazując nieefektywnych zastosowań i zmuszając użytkownika do poszukiwania alternatywnych rozwiązań dla innych typów iteratorów. Jeśli wydajność z iteratorami dostępu losowego jest nadal w zasięgu, powinieneś użyć distance
i udokumentować fakt, że algorytm działa lepiej z iteratorami dostępu losowego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-03 19:14:06
Zgodnie z http://www.cplusplus.com/reference/std/iterator/distance / , ponieważ vec.begin()
jest iteratorem dostępu losowego, metoda odległości używa operatora -
.
Więc odpowiedź jest taka sama, z punktu widzenia wydajności, ale może użycie distance()
jest łatwiejsze do zrozumienia, jeśli ktoś będzie musiał przeczytać i zrozumieć Twój kod.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-28 07:46:52
Użyłbym wariantu -
tylko dla std::vector
- jest całkiem jasne, co to znaczy, a prostota operacji (która nie jest więcej niż odejmowaniem wskaźnika) jest wyrażona przez składnię (distance
, z drugiej strony, brzmi jak Pitagoras w pierwszym czytaniu, prawda?). Jak wskazuje UncleBen, -
działa również jako twierdzenie statyczne w przypadku, gdy vector
zostanie przypadkowo zmieniona na list
.
Również myślę, że jest to o wiele bardziej powszechne - nie mają liczby, aby to udowodnić, choć. Argument Główny: it - vec.begin()
jest krótszy w kodzie źródłowym - mniej pisania, mniej miejsca. Ponieważ jest jasne, że właściwa odpowiedź na twoje pytanie sprowadza się do kwestii gustu, może to również być ważnym argumentem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-03 18:50:29
Oto przykład, aby znaleźć" wszystkie " wystąpienia 10 wraz z indeksem. Pomyślałem, że to pomoże.
void _find_all_test()
{
vector<int> ints;
int val;
while(cin >> val) ints.push_back(val);
vector<int>::iterator it;
it = ints.begin();
int count = ints.size();
do
{
it = find(it,ints.end(), 10);//assuming 10 as search element
cout << *it << " found at index " << count -(ints.end() - it) << endl;
}while(++it != ints.end());
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-26 05:40:24
Właśnie odkryłem to: https://greek0.net/boost-range/boost-adaptors-indexed.html
for (const auto & element : str | boost::adaptors::indexed(0)) {
std::cout << element.index()
<< " : "
<< element.value()
<< std::endl;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-24 19:04:07
Obok int float string itd., można umieścić dodatkowe dane do .drugi przy użyciu diff. typ:
std::map<unsigned long long int, glm::ivec2> voxels_corners;
std::map<unsigned long long int, glm::ivec2>::iterator it_corners;
Lub
struct voxel_map {
int x,i;
};
std::map<unsigned long long int, voxel_map> voxels_corners;
std::map<unsigned long long int, voxel_map>::iterator it_corners;
Kiedy
long long unsigned int index_first=some_key; // llu in this case...
int i=0;
voxels_corners.insert(std::make_pair(index_first,glm::ivec2(1,i++)));
Lub
long long unsigned int index_first=some_key;
int index_counter=0;
voxel_map one;
one.x=1;
one.i=index_counter++;
voxels_corners.insert(std::make_pair(index_first,one));
Z odpowiednim typem / / struktury można umieścić wszystko w .drugi zawiera numer indeksu, który jest zwiększany podczas wstawiania.
Zamiast
it_corners - _corners.begin()
Lub
std::distance(it_corners.begin(), it_corners)
Po
it_corners = voxels_corners.find(index_first+bdif_x+x_z);
Indeks jest po prostu:
int vertice_index = it_corners->second.y;
Przy użyciu typu GLM:: ivec2
Lub
int vertice_index = it_corners->second.i;
W przypadek typu danych struktury
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-29 20:22:47