|
-
April 16th, 2010, 04:09 AM
#1
check if a variable is inside a set of values
Hi
I wanted to know if there was a way to check if a variable was inside a set of values.
Like in the below given example, I want to know if n1 is either 5, 8, 27 or 2567
Is there a better way to do it than just using "if statement" ?
Code:
#include <iostream>
int main()
{
int n1;
if(n1 == 5 || n1 == 18 || n1 == 27 || n1 == 2567) //Is there a better way of achieving this
std :: cout << "good\n";
else
std :: cout << "bad\n";
return(0);
}
Thanks,
Muthu
-
April 16th, 2010, 04:28 AM
#2
Re: check if a variable is inside a set of values
Yes, there are many ways: the if/else or the switch statement, these two are for a small number of values.
But if you have a big number of values use an array or std::vector to store values and a function to search.
-
April 16th, 2010, 04:39 AM
#3
Re: check if a variable is inside a set of values
well as far as i see not really,
the thing you have now is ok for this amount of numbers, if you had more like 20 or something you could use an array or like Zlatomir said std::vector and using a loop check all the values inside the array/vector
-
April 16th, 2010, 04:51 AM
#4
Re: check if a variable is inside a set of values
If your values are iterable, then std::find should do just fine. If you plan on doing this search many times, you can sort your elements, and use std::binary_search for increased performance.
The simplest option would be to use an std::map though.
-
April 16th, 2010, 04:54 AM
#5
Re: check if a variable is inside a set of values
or like Zlaand using a loop check all the values inside the array/vector
No need for a loop in this case -- just use std::find().
Regards,
Paul McKenzie
-
April 16th, 2010, 05:53 AM
#6
Re: check if a variable is inside a set of values
Thank you so much for all your replies.
I had this vague view that there was a function called "any" ... hahah .. I was so wrong.
I suppose std :: find would suit my needs.
Thanks all
Muthu
-
April 16th, 2010, 08:18 AM
#7
Re: check if a variable is inside a set of values
If the set of numbers you're checking changes often, then use a std::set. If it does not, then use a sorted vector with std::binary_search.
-
April 16th, 2010, 08:44 AM
#8
Re: check if a variable is inside a set of values
If it's a constant set of numbers, use a switch.
Code:
switch (n){
case 5:
case 18:
case 27:
case 2567:
std::cout << "good" << std::endl;
break;
default:
std::cout << "bad" << std::endl;
break;
}
-
April 16th, 2010, 08:45 AM
#9
Re: check if a variable is inside a set of values
 Originally Posted by Muthuveerappan
I had this vague view that there was a function called "any"
Any is a keyword in Cobol and in SQL, not in C/C++.
Anyway, you can have something shorter and quicker than
Code:
if(n1 == 5 || n1 == 18 || n1 == 27 || n1 == 2567)
std :: cout << "good\n";
else
std :: cout << "bad\n";
With:
Code:
if (t[n1] == 'Y')
std :: cout << "good\n";
else
std :: cout << "bad\n";
But this requires a few lines of initialization:
Code:
char t[3000];
memset(t, 'N', sizeof(t));
t[5] = t[18] = t[27] = t[2567] = 'Y';
-
April 16th, 2010, 08:53 AM
#10
Re: check if a variable is inside a set of values
That strikes me as potentially dangerous since you could end up trying to read an invalid location. Not as big a deal as writing one, but who knows, there could be a 'Y' there.
The O(log n) options I outlined above are pretty good. Using a hash table is another option, but serious overkill unless the number of values you're checking is large, eg, over a thousand.
-
April 16th, 2010, 01:06 PM
#11
Re: check if a variable is inside a set of values
 Originally Posted by Lindley
That strikes me as potentially dangerous since you could end up trying to read an invalid location. Not as big a deal as writing one, but who knows, there could be a 'Y' there.
The O(log n) options I outlined above are pretty good. Using a hash table is another option, but serious overkill unless the number of values you're checking is large, eg, over a thousand.
If you are only looking for a range of integral values "existence" or "flag", you can use a bit array to store the "boolean bit flags", there's no need for a full blown hash table.
Code:
class CBitArray
{
public:
CBitArray(unsigned long dwMinValue,unsigned long dwMaxValue);
~CBitArray();
bool IsValueBitSet(unsigned long dwValue) const throw(std::exception);
void SetValueBit(unsigned long dwValue,bool bValue) throw(std::exception);
static CBitArray * CreateFromVector(const std::vector<unsigned long> & vValues);
protected:
unsigned long m_dwMinValue;
unsigned long m_dwMaxValue;
unsigned long m_dwRangeSize;
unsigned char * m_pData;
unsigned long & m_dwBitCount; // refers to m_dwRangeSize
unsigned long m_dwByteCount;
};
CBitArray::CBitArray(unsigned long dwMinValue,unsigned long dwMaxValue) : m_dwMinValue(dwMinValue),
m_dwMaxValue(dwMaxValue),m_dwRangeSize(dwMaxValue - dwMinValue + 1),m_pData(0),m_dwBitCount(m_dwRangeSize),
m_dwByteCount(0)
{
m_dwByteCount = m_dwBitCount >> 3;
if (m_dwBitCount & 7)
{
++m_dwByteCount;
}
m_pData = new unsigned char[m_dwByteCount];
for (unsigned long i = 0; i < m_dwByteCount; ++i)
{
m_pData[i] = 0;
}
}
CBitArray::~CBitArray()
{
if (m_pData != 0)
{
delete [] m_pData;
}
}
bool CBitArray::IsValueBitSet(unsigned long dwValue) const throw(std::exception)
{
bool bValueSet = false;
if (dwValue < m_dwMinValue || dwValue > dwValue)
{
std::exception e("Value out of range.");
throw(e);
}
const unsigned long dwTempValue = dwValue - m_dwMinValue;
const unsigned long dwByteIndex = dwTempValue >> 3;
const unsigned long dwBitIndex = dwTempValue & 7;
const unsigned char ucBitMask = 1 << dwBitIndex;
bValueSet = ( m_pData[dwByteIndex] & ucBitMask) != 0 ;
return bValueSet;
}
void CBitArray::SetValueBit(unsigned long dwValue,bool bValue) throw(std::exception)
{
if (dwValue < m_dwMinValue || dwValue > m_dwMaxValue)
{
std::exception e("Value out of range.");
throw(e);
}
const unsigned long dwTempValue = dwValue - m_dwMinValue;
const unsigned long dwByteIndex = dwTempValue >> 3;
const unsigned long dwBitIndex = dwTempValue & 7;
const unsigned char ucBitMask = 1 << dwBitIndex;
if (bValue == true)
{
m_pData[dwByteIndex] |= ucBitMask;
}
else
{
m_pData[dwByteIndex] &= ~ucBitMask;
}
}
CBitArray * CBitArray::CreateFromVector(const std::vector<unsigned long> & vValues)
{
CBitArray * pObject = 0;
unsigned long dwMinValue = 0xFFFFFFFF;
unsigned long dwMaxValue = 0;
std::vector<unsigned long>::const_iterator it = vValues.cbegin();
std::vector<unsigned long>::const_iterator end = vValues.cend();
while (it != end)
{
const unsigned long dwTempValue = *it;
if (dwTempValue < dwMinValue)
{
dwMinValue = dwTempValue;
}
if (dwTempValue > dwMaxValue)
{
dwMaxValue = dwTempValue;
}
++it;
}
pObject = new CBitArray(dwMinValue,dwMaxValue);
it = vValues.cbegin();
end = vValues.cend();
while (it != end)
{
pObject->SetValueBit(*it,true);
++it;
}
std::cout << "The minimum value is: " << dwMinValue << " The max value is " << dwMaxValue << std::endl;
return pObject;
}
int wmain(int argc, wchar_t * argv[])
{
std::vector<unsigned long> arValues;
std::cout << "Enter the amount of numbers you wish to enter: ";
unsigned long dwCount = 0;
std::cin >> dwCount;
if (dwCount != 0)
{
unsigned long dwValue = 0;
for (unsigned long i = 0; i < dwCount; ++i)
{
std::cout << "Enter the number: ";
std::cin >> dwValue;
arValues.push_back(dwValue);
}
CBitArray * pBitArray = CBitArray::CreateFromVector(arValues);
std::cout << "Can you remember one of those numbers? Enter one: ";
std::cin >> dwValue;
try
{
if (pBitArray->IsValueBitSet(dwValue) == true)
{
std::cout << "That was one of the numbers you entered." << std::endl;
}
else
{
std::cout << "That was not one of the numbers you entered." << std::endl;
}
}
catch(const std::exception & e)
{
std::cout << "Exception: " << e.what() << std::endl;
}
system("pause");
delete pBitArray;
}
return 0;
}
-
April 16th, 2010, 04:30 PM
#12
Re: check if a variable is inside a set of values
True, but no need to write your own; a std::bitset will work fine. (If you need to make it dynamic, then a std::vector<bool> will serve, although you should prefer a boost: ynamic_bitset if you have access to Boost.)
The set/hash set options become more appealing when the range of possible values is large.
-
April 17th, 2010, 07:42 PM
#13
Re: check if a variable is inside a set of values
 Originally Posted by Lindley
If the set of numbers you're checking changes often, then use a std::set. If it does not, then use a sorted vector with std::binary_search.
IIRC std::set is usually implemented as a binary search tree, so would using a vector offer any real advantage? Especially considering how much uglier it is to write "std::binary_search(myVec.begin(), myVec.end(), value)" everywhere as compared to "mySet.count(value)".
-
April 17th, 2010, 07:57 PM
#14
Re: check if a variable is inside a set of values
 Originally Posted by Speedo
IIRC std::set is usually implemented as a binary search tree, so would using a vector offer any real advantage? Especially considering how much uglier it is to write "std::binary_search(myVec.begin(), myVec.end(), value)" everywhere as compared to "mySet.count(value)".
I'm just echoing Effective STL here. Since a vector stores all the values in one place, looking something up in it with binary_search is going to be much more cache-efficient than in a std::set, unless your particular STL implementation takes steps to ensure that nodes in a single container are usually close together in memory.
-
April 17th, 2010, 08:07 PM
#15
Re: check if a variable is inside a set of values
If you need a "sorted vector" container, ie, a set with an array implementation, no need to write your own:
http://www.codeproject.com/KB/stl/sorted_vector.aspx
I've never tried it, so I can't grantee how good it is, but I doubt it's bad.
According to the article, a sorted_vector out performs a set for search operations by a factor of two (as explained by Meyers and echoed by Lindley).
The downside is the o(n) complexity on insertions.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|