views:

980

answers:

5

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?

+5  A: 
suspects.any? do |suspect, _|
  criminals.any? do |criminal, _|
    suspect == criminal
  end
end
sepp2k
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
probably worth breaking out the code into a short helper function with a descriptive name, e.g., if (intersect(l1,l2))
klochner
+1  A: 
klochner
should also point out that my version returns an object or nil, another reason to use any?
klochner
+2  A: 

Faster like this:

suspects.any? {|s,_| criminals.assoc(s)}
glenn mcdonald
A: 

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.
Swanand
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
Oh.. I wonder how I missed it..
Swanand
A: 

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.

Mike Woodhouse