I have a value 'Dog'
and an array ['Cat', 'Dog', 'Bird']
.
How do I check if it exists in the array without looping through it? Is there a simple way of checking if the value exists, nothing more?
|
You're looking for
|
|||||||||||||||||||||
|
There is an
OTOH, there is no As pointed out by others, the reverse method
Note that if you have many values in your array, they will all be checked one after the other (i.e.
A quick test reveals that calling A final closing note: be wary when using |
|||||||||
|
Try
|
|||||||||
|
Use
Or, if a number of tests are done,1 you can get rid of the loop (that even
1. I hope this is obvious but to head off objections: yes, for just a few lookups, the Hash[] and transpose ops dominate the profile and are each O(n) themselves. |
||||
|
If you want to check by a block, you could try any? or all?.
Details are here: http://ruby-doc.org/core-1.9.3/Enumerable.html |
|||||
|
Several answers suggest
The way to test the word presence without looping is by constructing a trie for your array. There are many trie implementations out there (google "ruby trie"). I will use
And now we are ready to test the presence of various words in your array without looping over it, in
|
|||||||||||||||||||||
|
This is another way to do this: use the Array#index method. It returns the index of the first occurrence of the element in the array. example:
index() can also take a block for example
here, return the index of the first word in the array that containing letter 'o'. |
|||||||||
|
If you don't want to loop, there's no way to do it with Arrays. You should use a Set instead.
Sets work internally like hashes, so Ruby doesn't need to loop through the collection to find items, since as the name implies, it generates hashes of the keys and creates a memory map so that each hash point to a certain point in memory. The previous example done with a Hash:
The downside is that Sets and hash keys can only include unique items and if you add a lot of items, Ruby will have to rehash the whole thing after certain number of items to build a new map that suits a larger keyspace. For more about this, I recommend you watch MountainWest RubyConf 2014 - Big O in a Homemade Hash by Nathan Long Here's a benchmark:
And the results:
|
|||||||||||||
|
There are multiple ways to accomplish this. A few of them are as follows:
|
|||||
|
This will tell you not only that it exists but also how many times it appears:
|
|||||
|
For what it's worth, The Ruby docs are an amazing resource for these kinds of questions. I would also take note of the length of the array you're searching through. The If you're working with a large (sorted) array, I would consider writing a binary search algorithm which shouldn't be too difficult and has a worst case of O(log n). Or if you're using Ruby 2.0, you can take advantage of |
|||||
|
There's the other way around, too! Suppose the array is [ :edit, :update, :create, :show ] - well perhaps the entire seven deadly/restful sins :) And further toy with the idea of pulling a valid action from some string - say
Solution
|
|||||
|
If you have on mind more values... you can try: Example: if Cat and Dog exist in the array:
Instead of:
Note: member? and include? are the same. This can do the work in one line! |
|||
|
If we want to not use
|
|||||
|
How about this way?
|
|||||
|
|
||||
|
if you don't want to use include? you can first wrap the element in an array and then check whether the wrapped element is equal to the intersection of the array and the wrapped element. This will return a boolean value based on equality.
|
|||
|
Here is one more way to do this:
|
|||||
|
|
|||
|
Ruby has 11 methods to find elements in an array. The preferred one is Or for repeated access, creating a set and then calling Here are all of them,
All of them return a
Translated to Ruby code this does about the following
Both We can use a set to get Here is the implementation of the
As you can see the I won't discuss the other 7 methods as they are all less efficient. There are actually even more methods with Don't use these,
|
||||
|
Fun fact, You can use
Notice the little All the usual magic behavior of the splat operator applies, so for example if |
|||
|