Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am trying to determine if the an element in one multi-dimensional array exists in another similarly structured array.

suspects = [['Rod', 100], ['Jane', 75], ['Freddy', 125]]
criminals = [['Bill', 75], ['Ted', 50], ['Rod', 75]]

The response I am looking for is either true or false. In the example above the response would be true because Rod exists in both arrays. The integer value has in the second tier array has no bearing.

How would I code such a test in typically Ruby-like succinctness?

share|improve this question

5 Answers 5

up vote 5 down vote accepted
suspects.any? do |suspect, _|
  criminals.any? do |criminal, _|
    suspect == criminal
  end
end
share|improve this answer
    
Thanks, works well. Out of interest, what is the best way to wrap this in an IF statement? I have simply placed it on one line and wrapped in parenthesis. Works, but looks a bit inelegant. –  aaronrussell Aug 10 '09 at 22:32
    
probably worth breaking out the code into a short helper function with a descriptive name, e.g., if (intersect(l1,l2)) –  klochner Aug 10 '09 at 23:03
1  
Out of curiosity, what does the underscore do here? For anyone else curious here is the documentation for it: ruby-doc.org/core/classes/Enumerable.html#M001500 –  Brian Armstrong Feb 20 '11 at 23:40
    
@Brian: Syntactically it's just a variable name. _ is conventionally used to signify a variable whose value we don't care about. –  sepp2k Feb 20 '11 at 23:42

Faster like this:

suspects.any? {|s,_| criminals.assoc(s)}
share|improve this answer

sepp2k beat me to it, but i have to submit just to show how close we were in implementation:


suspects.find do |suspect_name, _|
  criminals.find {|criminal_name, _| criminal_name == suspect_name}
 end 

I like his use of any?, but think the inner block should be inline :)

share|improve this answer
    
should also point out that my version returns an object or nil, another reason to use any? –  klochner Aug 10 '09 at 22:17

How about:

(suspect.size + criminal.size) > (suspect | criminals).size

Sample:

suspects = [['Rod', 100], ['Jane', 75], ['Freddy', 125]]
criminals = [['Bill', 75], ['Ted', 50], ['Rod', 75]]

guilty = (suspects.size + criminals.size) > (suspects | criminals).size
# Returns false. Since no common element was found in the merging.

criminals << ['Jane', 75]
guilty = (suspects.size + criminals.size) > (suspects | criminals).size
# Returns true. Since one element is common, merged array will be shorter by one.
share|improve this answer
    
I really like the approach, but you might want to read the question again: the second (numeric) part of the content items is not to be used for matching, so this doesn't do the job. –  Mike Woodhouse Aug 11 '09 at 8:14
    
Oh.. I wonder how I missed it.. –  Swanand Aug 11 '09 at 12:32

I'm not necessarily recommending this, but anther one-line option (two if you count the require) could be this:

require 'set'
(suspects.map{|s| s[0]}.to_set & criminals.map{|c| c[0]}.to_set).size > 0

=> true

It builds arrays from the first element of each item then converts it to a Set. Set has the & (intersect) method and we look at the size of the result for our answer.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.