2

In c++ I have an array and I am trying to check if there is a certain element in the array. Here is my array:

string choices[3] = {"a", "b", "c"}

I want it so that it prints out true if the user input is present in the array so if the user enters "b" then it will print true and give me the array index. This is like the Python version of in or find. I know I can just use a for loop to go over all the elements, but is there a more efficient way? Thanks.

Prince
  • 20,353
  • 6
  • 39
  • 59
Nirvik Baruah
  • 1,643
  • 2
  • 19
  • 20
  • 1
    Have a look at `std::find`. – juanchopanza Feb 17 '14 at 13:33
  • 2
    There's nothing more efficient than a loop (unless the array is sorted or otherwise structured to help searching); but there are algorithms like `std::find` which might be neater than a loop. – Mike Seymour Feb 17 '14 at 13:34
  • I don't think you want to have an array of strings. Because you are getting all the disadvantages of an array without any of the advantages since the strings still need to be copied and runtime constructed. Either use array of const char pointers to get efficiency or vector of strings to get safety and convenience. – Jan Hudec Feb 17 '14 at 13:40

4 Answers4

2

To find index you can use the following code:

int x = std::distance(choices, std::find(choices, choices + 3, "b"));

here, distance and find method can be found in <algorithm> header.

Emu
  • 5,763
  • 3
  • 31
  • 51
  • Template argument deduction will fail for this example because of mismatched types. You need to use `choices + 0` instead of `choices`. – Simple Feb 17 '14 at 13:42
  • I prefer `std::begin(choices)` and `std::end(choices)`. Note that if x equals the size of `choices`, `choices` does not contain `"b"` – Enigma Feb 17 '14 at 13:45
1

You can use standard algorithm std::find declared in header <algorithm> It resolves two tasks. It can say whether a string is present in a container and it can provide the index of the first found element.

If you need only to determine whether a string is present in a container you can use standard algorithm std::any_of

The both algorithms have linear complexity.

If a container (for example an array) is ordered then you can use standard algorithm std::binary_search to determine whether a string is present in the container.

An example that demonstrates the usage of standard algorithm std::find

#include <iostream>
#include <iomanip>
#include <string>
#include <algorithm>
#include <iterator>

int main()
{
   std::string choices[] = { "a", "b", "c" };

   std::cout << "Enter a string: ";

   std::string s;
   std::cin >> s;

   auto it = std::find( std::begin( choices ), std::end( choices ), s );

   bool in_array = it != std::end( choices );

   std::cout << "String "\" << s << "\" is present in the array = " 
             << std::boolalpha << in_array << std::endl;
   if ( in_array ) 
   {
      std::cout << "It is " << std::distance( std::begin( choices ), it ) 
                << " element in the array" << std::endl;
   }
}

If you need a more complex condition searching an element in a container you can use standard algorithm std::find_if that accepts a predicate as an argument.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

std::find returns an iterator to the element in the array if it's found or the end iterator otherwise:

auto const last = std::end(choices);
auto const pos = std::find(std::begin(choices), end, "b");
if (last != pos) {
    // Use pos here.
}

If you don't need to do anything with the element then you can use any_of:

if (std::any_of(std::begin(choices), std::end(choices),
                [](std::string const& s) { return "b" == s; })
{
    // "b" is in the array.
}

Both of these functions are just loops internally, they won't be any quicker than a hand written loop. If your array is sorted then you can use std::lower_bound instead of std::find and std::binary_search instead of std::any_of.

Simple
  • 13,992
  • 2
  • 47
  • 47
0

There is no more efficient way unless the items are somehow ordered. Consider that the element you want to find could, theoretically, be at any index, including the last index that you would check.

If you want to find it efficiently, use std::set. Then you can use set::count(item) > 0 to decide if item is in the set.

Also, in python, it effectively does a loop over all elements when you test whether an item is in a list item in [itemA, itemB, itemC] or in a tuple item in (itemA, itemB, itemC). It is only when you use python's set and frozenset that this search is very fast.

I would recommend using the function std::find if you don't want to write the O(n) loop yourself, and using the std::set class if you want faster lookup.

user
  • 7,123
  • 7
  • 48
  • 90