0

I have this array:

[[4, 50], [2, 28], [1, 4], [4, 41], [1, 9], [2, 25]]

I wish to construct an array consisting of those tuples [f,l] of this array such that there is no tuple [g,h] preceding [f,l] for which g==f. The selected tuples are to be in the same order as in the original array.

[[4, 50], [2, 28], [1, 4]]

Example if there are any more arrays that begin with 4 or 1 it should be deleted. It could be any integer, 4 and 1 is only an example.

11
  • 3
    group by first element and select only the first item of the group. Commented Jun 25, 2014 at 14:39
  • Why is [2, 25] deleted? Commented Jun 25, 2014 at 14:41
  • @sawa - Because there have already been a array starting with 2 ´[2, 28]´ Commented Jun 25, 2014 at 14:42
  • 1
    @Railsbeginner But it does not start with 4 or 1. Commented Jun 25, 2014 at 14:43
  • 2
    Rails, you've got two downvotes and two votes to close. Let's rescue the question. It's a good one and @Stefan provided a very good answer. What you need to do is edit and insert something like the following, right before "I want the result to be:": "I wish to construct an array consisting of those tuples [f,l] of this array such that there is no tuple [g,h] preceding [f,l] for which g==f. The selected tuples are to be in the same order as in the original array." Yes, that's a bit of a mouthful, but I think it states unambiguously what you are trying to accomplish. Commented Jun 25, 2014 at 16:52

2 Answers 2

7

Array#uniq seems to work:

[[4, 50], [2, 28], [1, 4], [4, 41], [1, 9], [2, 25]].uniq(&:first)
#=> [[4, 50], [2, 28], [1, 4]]
Sign up to request clarification or add additional context in comments.

4 Comments

This is better than mine.
@CarySwoveland the documentation doesn't specify which duplicate is preserved and which is removed. The behavior could be implementation specific.
I expect that's a reflection on the incompleteness of the documentation, rather than evidence that maintenance of order was intentionally omitted from the spec. It would make no sense for uniq with a parameter to return a value that is preceded in the array by a matching value. Also, it is part of the spec ("yields items in order") for Ruby MRI.
@CarySwoveland thanks for the RubySpec pointer. The failing example would be "compares elements based on the value returned from the block", returning [1, 4] instead of [1, 2] if the implementation would keep the last item
0

I can't improve on @Stefan's answer, but here's another way that merely steps through the elements of the array:

a = [[4, 50], [2, 28], [1, 4], [4, 41], [1, 9], [2, 25]]

a.each_with_object([]) { |(f,l),a| a<<[f,l] unless a.any? { |g,_| g==f } }
  #=> [[4, 50], [2, 28], [1, 4]]

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.