473,416 Members | 1,818 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

finding an index in an STL vector<>

Joe
I have a: vector<string> which contains a few dozen elements.

I want to find the index of the element containing a certain string.

for example:

vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

int index = distance(strings.begin(), find(strings.begin(),
strings.end(), string("xyz")));

cout << index << endl; // should print out a '1', the index of "xyz"

The above line using 'distance' seems pretty terrible to me. Please
tell me that there a better way?

Thanks in advance,
Joe
Jul 22 '05 #1
6 3754
"Joe" <jo********@gmail.com> wrote in message
news:60**************************@posting.google.c om...
I have a: vector<string> which contains a few dozen elements.

I want to find the index of the element containing a certain string.

for example:

vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

int index = distance(strings.begin(), find(strings.begin(),
strings.end(), string("xyz")));

cout << index << endl; // should print out a '1', the index of "xyz"

The above line using 'distance' seems pretty terrible to me. Please
tell me that there a better way?


Ah, it's not that bad. The explicit construction of the std::string can be
eliminated to make it a little prettier, right? I can't think of anything
better offhand. If you think it's ugly, wrap it.

// optionally a template
std::size_t index_of_element( std::vector<std::string&>& vec, const
std::string& elem );

int index = index_of_element( strings, "xyz" );

But why do you want the index when you already have an iterator?

--
David Hilsee
Jul 22 '05 #2
David Hilsee wrote:
"Joe" <jo********@gmail.com> wrote in message
news:60**************************@posting.google.c om...
I have a: vector<string> which contains a few dozen elements.

I want to find the index of the element containing a certain string.

for example:

vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

int index = distance(strings.begin(), find(strings.begin(),
strings.end(), string("xyz")));

cout << index << endl; // should print out a '1', the index of "xyz"

The above line using 'distance' seems pretty terrible to me. Please
tell me that there a better way?

Ah, it's not that bad. The explicit construction of the std::string can be
eliminated to make it a little prettier, right? I can't think of anything
better offhand. If you think it's ugly, wrap it.

// optionally a template
std::size_t index_of_element( std::vector<std::string&>& vec, const
std::string& elem );

int index = index_of_element( strings, "xyz" );

But why do you want the index when you already have an iterator?


Hi, this I'm the original poster 'Joe' just using a different new client...

Thanks for your quick response!

Why do I want an index when I already have an iterator?

Well, I had a class like this:

class foo {
[other class members]
string _bar;
public:
string bar() { return _bar; } // my reader function
bar([other parameters], bar) _bar(bar) {} // my constructor
}

The problem is that I have ten's of millions of objects instantiated
from this class, and I don't have enough RAM (and my machine can't hold
anymore than the 1GB it has).

So, since I know that there are only about 10 or 20 unique types of
'bar' I would just store them all in a static vector and store an index
(which only needs to be a char because there are only 10 or 20 unique
strings) to that vector in each object. So, I ended up with this:

class foo_new {
[ other class members]
static vector<string> mystrings;
char _bar_index; // this is just an index to the mystrings element
public:
string bar() { return mystrings[bar_index]; } // my reader function
foo_new([other parameters], string bar) { // constructor
int index = distance(strings.begin(), find(strings.begin(),
strings.end(), bar));
if(index != strings.end()) {
_bar_index = index;
} else {
_bar_index = strings.size();
strings.push_back(bar);
}
}
}

So, foo_new objects now have 'char bar_index' instead of 'string bar'
which will save me hundreds of megabytes.

If you can propose a better way of getting a similar result, I will be
both grateful and impressed.

-- Joe
Jul 22 '05 #3
"Joe Harris" <NO_SPAMjoe.harris@KILL_ALL_SPAMMERSgmail.com> wrote in message
news:Xm******************@bignews3.bellsouth.net.. .
<snip>
Hi, this I'm the original poster 'Joe' just using a different new client...
Thanks for your quick response!

Why do I want an index when I already have an iterator?

Well, I had a class like this:

class foo {
[other class members]
string _bar;
public:
string bar() { return _bar; } // my reader function
bar([other parameters], bar) _bar(bar) {} // my constructor
}

The problem is that I have ten's of millions of objects instantiated
from this class, and I don't have enough RAM (and my machine can't hold
anymore than the 1GB it has).

So, since I know that there are only about 10 or 20 unique types of
'bar' I would just store them all in a static vector and store an index
(which only needs to be a char because there are only 10 or 20 unique
strings) to that vector in each object. So, I ended up with this:

class foo_new {
[ other class members]
static vector<string> mystrings;
char _bar_index; // this is just an index to the mystrings element
public:
string bar() { return mystrings[bar_index]; } // my reader function
foo_new([other parameters], string bar) { // constructor
int index = distance(strings.begin(), find(strings.begin(),
strings.end(), bar));
if(index != strings.end()) {
_bar_index = index;
} else {
_bar_index = strings.size();
strings.push_back(bar);
}
}
}

So, foo_new objects now have 'char bar_index' instead of 'string bar'
which will save me hundreds of megabytes.

If you can propose a better way of getting a similar result, I will be
both grateful and impressed.


Well, I can't think of a better way to do what you're doing. It looks like
a flyweight. However, given that there are tens of millions of these
objects, I would probably verify a few things, if I were you. First, make
sure that there isn't a way you can reduce the number of elements. Can
these objects, or certain member of these objects, be computed on the fly?
Second, make sure that there aren't more members that can benefit from using
that static table. Third, make sure that you are realizing the benefits of
using a char instead of a std::vector<std::string>::size_type and that your
code doesn't accidentally go beyond the range of a char. Other than that,
without knowing anything else, I'd say that the implementation looks pretty
solid.

If the call to distance still looks odd to you, you can use subtraction
instead, or separate it out into two different lines.

--
David Hilsee
Jul 22 '05 #4
In article <60**************************@posting.google.com >,
jo********@gmail.com (Joe) wrote:
I have a: vector<string> which contains a few dozen elements.

I want to find the index of the element containing a certain string.

for example:

vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

int index = distance(strings.begin(), find(strings.begin(),
strings.end(), string("xyz")));

cout << index << endl; // should print out a '1', the index of "xyz"

The above line using 'distance' seems pretty terrible to me. Please
tell me that there a better way?


That does look a little yuk. How about this?

// this is a bit ugly, but its use is much cleaner. See below
template < typename InputIterator, typename EqualityComparable >
typename iterator_traits<InputIterator>::difference_type
Index(const InputIterator& begin, const InputIterator& end,
const EqualityComparable& item) {
return distance(begin, find(begin, end, item));
}

int main() {
vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

assert(Index(strings.begin(), strings.end(), "xyz") == 1);
assert(Index(strings.begin(), strings.end(), "WWW") ==
strings.size()); //line 1
assert(Index(strings.rbegin(), strings.rend(), "lmnop") == 0);//line 2
cout << "OK";
}

Note how it handles error conditions (line 1.) Also note how it handles
reverse iterators (line 2)...
Jul 22 '05 #5
David Hilsee wrote:
"Joe Harris" <NO_SPAMjoe.harris@KILL_ALL_SPAMMERSgmail.com> wrote in message
news:Xm******************@bignews3.bellsouth.net.. .
<snip>
Hi, this I'm the original poster 'Joe' just using a different new


client...
Thanks for your quick response!

Why do I want an index when I already have an iterator?

Well, I had a class like this:

class foo {
[other class members]
string _bar;
public:
string bar() { return _bar; } // my reader function
bar([other parameters], bar) _bar(bar) {} // my constructor
}

The problem is that I have ten's of millions of objects instantiated
from this class, and I don't have enough RAM (and my machine can't hold
anymore than the 1GB it has).

So, since I know that there are only about 10 or 20 unique types of
'bar' I would just store them all in a static vector and store an index
(which only needs to be a char because there are only 10 or 20 unique
strings) to that vector in each object. So, I ended up with this:

class foo_new {
[ other class members]
static vector<string> mystrings;
char _bar_index; // this is just an index to the mystrings element
public:
string bar() { return mystrings[bar_index]; } // my reader function
foo_new([other parameters], string bar) { // constructor
int index = distance(strings.begin(), find(strings.begin(),
strings.end(), bar));
if(index != strings.end()) {
_bar_index = index;
} else {
_bar_index = strings.size();
strings.push_back(bar);
}
}
}

So, foo_new objects now have 'char bar_index' instead of 'string bar'
which will save me hundreds of megabytes.

If you can propose a better way of getting a similar result, I will be
both grateful and impressed.

Well, I can't think of a better way to do what you're doing. It looks like
a flyweight. However, given that there are tens of millions of these
objects, I would probably verify a few things, if I were you. First, make
sure that there isn't a way you can reduce the number of elements. Can
these objects, or certain member of these objects, be computed on the fly?
Second, make sure that there aren't more members that can benefit from using
that static table. Third, make sure that you are realizing the benefits of
using a char instead of a std::vector<std::string>::size_type and that your
code doesn't accidentally go beyond the range of a char. Other than that,
without knowing anything else, I'd say that the implementation looks pretty
solid.

If the call to distance still looks odd to you, you can use subtraction
instead, or separate it out into two different lines.


I am now using subtraction and it looks better. I'm still getting up to
speed with STL and I wanted to make sure that what I was doing wasn't
too strange. It seemed odd to me that there was no more concise way to
express my thought, but I guess that -- as you say -- people usually are
happy with an iterator.

-- Joe
Jul 22 '05 #6
Daniel T. wrote:
In article <60**************************@posting.google.com >,
jo********@gmail.com (Joe) wrote:

I have a: vector<string> which contains a few dozen elements.

I want to find the index of the element containing a certain string.

for example:

vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

int index = distance(strings.begin(), find(strings.begin(),
strings.end(), string("xyz")));

cout << index << endl; // should print out a '1', the index of "xyz"

The above line using 'distance' seems pretty terrible to me. Please
tell me that there a better way?

That does look a little yuk. How about this?

// this is a bit ugly, but its use is much cleaner. See below
template < typename InputIterator, typename EqualityComparable >
typename iterator_traits<InputIterator>::difference_type
Index(const InputIterator& begin, const InputIterator& end,
const EqualityComparable& item) {
return distance(begin, find(begin, end, item));
}

int main() {
vector<string> strings;
strings.push_back("abc");
strings.push_back("xyz");
strings.push_back("lmnop");

assert(Index(strings.begin(), strings.end(), "xyz") == 1);
assert(Index(strings.begin(), strings.end(), "WWW") ==
strings.size()); //line 1
assert(Index(strings.rbegin(), strings.rend(), "lmnop") == 0);//line 2
cout << "OK";
}

Note how it handles error conditions (line 1.) Also note how it handles
reverse iterators (line 2)...


Interesting... thanks.
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Marc Schellens | last post by:
my dinkumware docu says, vector<...>::rbegin() returns an iterator which points just BEYOND the end of the controlled sequence. Is that true? so I cannot say: for( riter i=v.rbegin(); i !=...
2
by: john smith | last post by:
Hi, when there is a vector<> of pointers to some objects, does calling resize cause vector to call delete on each object, or is there a memory leak problem? for example: struct base {//some...
10
by: Stefan Höhne | last post by:
Hi, as I recon, std::vector::clear()'s semantics changed from MS VC++ 6.0 to MS' DOT.NET - compiler. In the 6.0 version the capacity() of the vector did not change with the call to...
4
by: Anu | last post by:
Hi, We have a class that has its own overloaded operator new and whose prototype seems to correspond to the standard placement new :- class AppClass { public: operator new (size_t size,...
1
by: OriginalCopy | last post by:
This is a demonstrative code which could be used for debugging purposes. And yet I don't know how to insert the necessary data on line 63, purely syntactically speaking ? I'm a beginner with STL, and...
5
by: Numeromancer | last post by:
From the C++-FAQ Lite: http://www.parashift.com/c++-faq-lite/containers.html#faq-34.3 ---------------------------- 34.3] Is the storage for a std::vector<Tguaranteed to be contiguous? Yes. ...
8
by: jacek.dziedzic | last post by:
Hi! I need to be able to track memory usage in a medium-sized application I'm developing. The only significant (memory-wise) non- local objects are of two types -- std::vector<and of a custom...
3
by: Rune Allnor | last post by:
Hi folks. I have a function that takes an element in a vector as argument. The naive interface goes as float computeSomething(const std::vector<float>& v, size_t i) { size_t j = i-1; size_t...
1
by: iammilind | last post by:
In one of my code, I was using vector<> for certain class. In one of my struct, I have 'const' member data. However, vector<>::clear() throws compile error with that:...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.