3

I want to remove a pair of 'duplicates' from an array of strings, where each element has the form R1,R2, with varying numbers. In my case, a duplicate would be R2,R1 because it has the same elements of R1,R2 but inverted.

Given:

a = ['R1,R2', 'R3,R4', 'R2,R1', 'R5,R6']

The resulting array should be like so:

a = ['R1,R2', 'R3,R4', 'R5,R6']

How could I remove the duplicates so I would have the following?

4 Answers 4

6

A solution with Set

require 'set' 

a.uniq { |item| Set.new(item.split(",")) }  # => ["R1,R2", "R3,R4", "R5,R6"]
Sign up to request clarification or add additional context in comments.

Comments

5

Here is a working example :

array = ['R1,R2', 'R3,R4', 'R2,R1', 'R5,R6']

array.uniq { |a| a.split(',').sort }

4 Comments

You can shorten this to array.uniq {|a| a.split(',').sort.join(',') }.
Why do you need the join? It works even without that :)
You are right :) It was a leftover from the initial answer.
@Ursus the desired output in the question is a array of strings - not an array of arrays.
0

try this,

def unique(array)
    pure = Array.new
    for i in array
        flag = false
        for j in pure
            flag = true if (j.split(",").sort == i.split(",").sort)
        end
        pure << i unless flag
    end
    return pure
end

reference: https://www.rosettacode.org/wiki/Remove_duplicate_elements#Ruby

1 Comment

I don't mean this as an insult but the solution you provided is very non-idiomatic.
0

If the elements of your array are "pairs", they should maybe be actual pairs and not strings, like this:

pairs = [['R1', 'R2'], ['R3', 'R4'], ['R2', 'R1'], ['R5', 'R6']]

And, in fact, since order doesn't seem to matter, it looks like they really should be sets:

require 'set'

sets = [Set['R1', 'R2'], Set['R3', 'R4'], Set['R2', 'R1'], Set['R5', 'R6']]

If that is the case, then Array#uniq will simply work as expected:

sets.uniq
#=> [#<Set: {"R1", "R2"}>, #<Set: {"R3", "R4"}>, #<Set: {"R5", "R6"}>]

So, the best way would be to change the code that produces this value to return an array of two-element sets.

If that is not possible, then you should transform the value at your system boundary when it enters the system, something like this:

sets = a.map {|el| el.split(',') }.map(&Set.method(:new))

2 Comments

That doesn't really solves what OP posted, since you actually modified the specification of the problem.
@oxfist the recommendation to transform the values into actual sets is spot on though.

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.