2

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 Answers 5

5
suspects.any? do |suspect, _|
  criminals.any? do |criminal, _|
    suspect == criminal
  end
end
Sign up to request clarification or add additional context in comments.

4 Comments

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.
probably worth breaking out the code into a short helper function with a descriptive name, e.g., if (intersect(l1,l2))
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: Syntactically it's just a variable name. _ is conventionally used to signify a variable whose value we don't care about.
3

Faster like this:

suspects.any? {|s,_| criminals.assoc(s)}

Comments

2

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 :)

1 Comment

should also point out that my version returns an object or nil, another reason to use any?
0

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.

1 Comment

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.
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.